Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django's HttpResponseRedirect is http instead of https

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?

like image 760
permike Avatar asked Jan 05 '17 10:01

permike


People also ask

Can you go from HTTPS to HTTP?

When you add an SSL certificate to a domain on your hosting account, the domain will default to being served over HTTPS. If you do not want your site to use HTTPS to serve your site securely, you can change the default from HTTPS to HTTP.

How do I redirect all HTTPS requests to HTTP?

In order for something to redirect HTTPS to HTTP, something must be listening on the HTTPS port. Your client must first open a SSL/TLS connection to the port serving HTTPS, HTTP traffic is tunneled through the SSL/TLS connection and the server will respond with a redirect to the HTTP port.


1 Answers

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.

like image 198
Antonis Christofides Avatar answered Oct 07 '22 00:10

Antonis Christofides