Opened 5 months ago

Last modified 3 months ago

#31354 assigned Bug

HttpRequest.get_host() doesn't include the port from META['HTTP_X_FORWARDED_PORT'].

Reported by: dgcgh Owned by: dgcgh
Component: HTTP handling Version: master
Severity: Normal Keywords: request get_host build_absolute_uri
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: yes
Needs tests: no Patch needs improvement: yes
Easy pickings: yes UI/UX: no

Description

request.get_port() should include the port of the authority if it is not 80 for http or 443 for https. Currently this does not happen when HTTP_X_FORWARDED_HOST is present in request.META.

This causes issues for e.g. request.build_absolute_uri() if the django app is running behind a reverse proxy on a non-standard port.

Example would be: nginx is listening on port 8443 and forwarding to a django server listening on port 8001:

server {
    listen      8443 ssl;
    server_name         localhost.example.com

   location / {
        proxy_pass  http://localhost:8001;
        # include     /etc/nginx/uwsgi_params;
        proxy_cache_bypass  $http_upgrade;

        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        "upgrade";
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host  $host;
        proxy_set_header X-Forwarded-Port  $server_port;
    }
}

In this case URIs built with request.build_absolute_uri() in a django app will exclude the port, i.e.:
request.build_django_uri("/") == "https://localhost.example.com/"
where it should return "https://localhost.example.com:8443/"

Change History (8)

comment:2 Changed 5 months ago by dgcgh

Owner: changed from nobody to dgcgh
Status: newassigned

comment:3 Changed 5 months ago by dgcgh

I think the problem here might be that django assumes X-Forwarded-Host will include the port number, as opposed to putting the port number in X-Forwarded-Port.

I can get the correct behavior by setting the nginx header as:

proxy_set_header X-Forwarded-Host  $host:$server_port;

and disabling USE_X_FORWARDED_PORT .
I take it that X-Forwarded-Port is not popular, so maybe this bug is not worth fixing, but I will update my PR with a more explicit solution.

comment:4 Changed 5 months ago by Florian Apolloner

LGTM, ses my comment on the PR for a small change.

comment:5 Changed 5 months ago by felixxm

Component: UncategorizedHTTP handling
Summary: When I am using a reverse proxy on a non-standard port request.get_host() does not include the portHttpRequest.get_host() doesn't include the port from META['HTTP_X_FORWARDED_PORT'].
Triage Stage: UnreviewedAccepted
Version: 3.0master

comment:6 Changed 5 months ago by felixxm

Patch needs improvement: set

comment:7 Changed 5 months ago by felixxm

Needs documentation: set

comment:8 Changed 3 months ago by felixxm

Note: See TracTickets for help on using tickets.
Back to Top