5

I am working on a Django project where users will have custom info given to them depending on their location. In order to do this, I use their IP address to identify their country. In order to keep data in the database consistent, I need to make sure I have an accurate IP.

I understand that using META usually uses headers sent by the client's browser, but I don't know if that applies to the REMOTE_ADDR attribute.

TLDR: what is the difference between HttpRequest.get_host() and HttpRequest.META['REMOTE_ADDR']?

dirtshell
  • 161
  • 2
  • 12

1 Answers1

6

The difference between HttpRequest.get_host() and HttpRequest.META['REMOTE_ADDR'] is that the first one checks IP in the following headers in order of decreasing preference:

  1. HTTP_X_FORWARDED_HOST
  2. HTTP_HOST
  3. SERVER_NAME combined with SERVER_PORT

whereas the second one check the IP in the header REMOTE_ADDR.

There is a huge difference in the type of information returned: get_host() will give you the name of the server hosting your application, not the IP of the client.

More in detail, here is the implementation of get_host():

def get_host(self):
    """Returns the HTTP host using the environment or request headers."""
    # We try three options, in order of decreasing preference.
    if settings.USE_X_FORWARDED_HOST and (
        'HTTP_X_FORWARDED_HOST' in self.META):
        host = self.META['HTTP_X_FORWARDED_HOST']
    elif 'HTTP_HOST' in self.META:
        host = self.META['HTTP_HOST']
    else:
        # Reconstruct the host using the algorithm from PEP 333.
        host = self.META['SERVER_NAME']
        server_port = str(self.META['SERVER_PORT'])
        if server_port != ('443' if self.is_secure() else '80'):
            host = '%s:%s' % (host, server_port)

    allowed_hosts = ['*'] if settings.DEBUG else settings.ALLOWED_HOSTS
    domain, port = split_domain_port(host)
    if domain and validate_host(domain, allowed_hosts):
        return host
    else:
        msg = "Invalid HTTP_HOST header: %r." % host
        if domain:
            msg += "You may need to add %r to ALLOWED_HOSTS." % domain
        raise DisallowedHost(msg)

If you want to check for client IP address, here are some headers that could be worth checking (see Getting the client IP address: REMOTE_ADDR, HTTP_X_FORWARDED_FOR, what else could be useful?):

  • REMOTE_ADDR
  • HTTP_X_FORWARDED_FOR
  • HTTP_CLIENT_IP
  • HTTP_X_FORWARDED_FOR can be comma delimited list of IPs
  • HTTP_X_FORWARDED
  • HTTP_X_CLUSTER_CLIENT_IP
  • HTTP_FORWARDED_FOR
  • HTTP_FORWARDED

If you don't know which one to pick (if not all), you could log those headers and pragmatically add new checkings over time.

Community
  • 1
  • 1
Benjamin Toueg
  • 10,511
  • 7
  • 48
  • 79