You deploy with nginx and Gunicorn and your site uses HTTPS. If Django occasionally returns HttpResponseRedirect or similar, you may find that the redirect sends you back to HTTP. Here’s how to fix it.
In the nginx configuration (inside the location
block), specify this:
proxy_redirect off; proxy_set_header X-Forwarded-Proto $scheme; |
The proxy_redirect off
statement tells nginx that, if the backend returns an HTTP redirect, it should leave it as is. By default, nginx assumes the backend is stupid and tries to fix the response; if, for example, the backend returns an HTTP redirect that says “redirect to http://localhost:8000/somewhere”, nginx replaces it with something similar to “http://yourowndomain.com/somewhere”. But Django isn’t stupid (or it can be configured to not be stupid), and it will typically return a relative URL. If nginx attempts to “fix” the relative URL, it will likely break things. Instead, we use proxy_redirect off
so that nginx merely passes the redirection as is.
The second line is only necessary if your Django project ever uses request.is_secure()
or similar. It’s a good idea to have it because even if it doesn’t today it will tomorrow, and it does no harm. Django does not know whether the request has been made through HTTPS or plain HTTP; nginx knows that, but the request it subsequently makes to the Django backend is always plain HTTP. We tell nginx to pass this information with the X-Forwarded-Proto
HTTP header, so that related Django functionality such as request.is_secure()
works properly. You will also need to set SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
in your settings.py
.