Django's HttpResponseRedirect is http instead

2020-02-09 11:08发布

问题:

My server runs Django + Gunicorn + nginx.

I have added an SSL certificate and configured nginx to redirect http to https. When an https request is received, nginx passes it to Gunicorn as http.

My program sometimes returns HttpResponseRedirect, and the browser gets a redirect response and re-requests as http, so nginx redirects to https.

How can I avoid this? How can I configure the server so that the first redirection points directly to an https URL?

回答1:

In the nginx configuration (inside the location block), specify this:

proxy_redirect off;
proxy_set_header X-Forwarded-Proto $scheme;

The proxy_redirect 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 be smart; if 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).

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.