django.http.get_host() breaks reverse proxying on apache
|Reported by:||Kellen||Owned by:||nobody|
|Severity:||Normal||Keywords:||redirect httpresponseredirect get_host reverse proxy squid apache|
|Cc:||kellen@…||Triage Stage:||Design decision needed|
|Has patch:||yes||Needs documentation:||no|
|Needs tests:||yes||Patch needs improvement:||no|
django.http.HttpResponseRedirect uses django.http.get_host() to get the hostname for relative redirects, but generates incorrect redirects when an app is behind a reverse proxy. In particular, get_host() uses the HTTP_X_FORWARDED_HOST, which will be the proxying domain rather than the proxied-to domain. This is bad when a proxy is being used to avoid part of /the/path/to/an/app/, since the whole path will be appended to the proxying domain, which will then rewrite it for the proxied-to domain and most often 404.
As an example:
I have a non-fancy django app, which uses HttpResponseRedirect to forward from various pages to others (say, on successful form submission). This lives on one domain, called backend. On another domain, frontend, I am using apache2 to reverse proxy to part of the application on backend.
When my app successfully adds a new item, it redirects from the add view at /app/object/add/ to the object view at /app/object/id/. This works when one adds an object while accessing backend directly. When one adds an object through frontend, however, a redirect is issued to the correct path on backend, but on the frontend domain. Backend should issue a redirect to: backend.com/app/object/id/, which apache should rewrite to frontend.com/object/id/ with ProxyPassReverse, which the browser should then attempt to access, and /object/id/ should be rewritten to /app/object/id/ on backend. What happens instead is a redirect to frontend.com/app/object/id/ is issued, the browser accesses the path, and it is rewritten to /app/app/object/id/ on backend, and a 404 results.
<VirtualHost xxx.xxx.xxx.xxx> ServerAdmin admin@frontend DocumentRoot /var/www/ ServerName www.frontend.com ServerAlias frontend.com ProxyPass / http://frontend.com/app/ ProxyPassReverse / http://frontend.com/app/ SetOutputFilter proxy-html ProxyHTMLURLMap http://frontend.com/app/ / </VirtualHost>
Change History (18)
comment:1 Changed 9 years ago by
|Patch needs improvement:||unset|
comment:2 Changed 9 years ago by
|Component:||Uncategorized → HTTP handling|
|Keywords:||redirect httpresponseredirect get_host reverse proxy squid apache added|