We always host Django app behind a proxy server(apache or nginx) in production, the connection from your client and the proxy server may be(better be) https. However, between the proxy server and Django app(gunicorn or whatever you’re using) is usually http. So Django thinks that the client is using http, and returns all hyperlink including media link & hyperlink fields using http protocol.

Solution One

This sometimes is not a big problem, as we can force all http connection to our proxy server to use https like the following.

Redirect permanent / https://example.com/

This may solve the security problem but what if your client does not support http(IOS, WechatApp etc.)?

Solution Two(prefered)

The best way to solve this is to let Django know the protocol that your client is using.

As per Django’s documentation, it uses request object’s is_secure() method to determine if the caller is using https. Since the headers are stripped by our proxy server, is_secure() will always return False resulting in http appears in hyperlinks.

Now we know the reason behind this, solving the problem becomes trivial.

Use one of Django’s setting


this means that if the request has a header X_FORWARDED_PROTO with value https, Django considers it to be secure and will use https in hyperlinks.

And don’t forget to forward protocol in your proxy server, here is an example in Apache.

RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}

Problem solved 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *