menu

Questions & Answers

Django - request.is_secure always returns False

I'm running a Django project on a DigitalOcean VPS using Nginx and Gunicorn. I made sure that i'm using HTTPS, but for some reason using request.is_secure() always returns False, and request.scheme returns HTTP, even though i made sure it's VPS.

What could be the reason for that? Here is my nginx config:

server {
    listen 80;
    server_name MY.SERVER.com;

    location / {
        include proxy_params;
        proxy_set_header        X-Forwarded-Proto           $scheme;
        proxy_pass http://unix:/var/www/proj/myproj.sock;

    }
}

And i also made sure to add to my Django settings SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https'). Any advice is appreciated

Comments:
2023-01-19 00:05:06
Isn't port 80 always going to be http?
2023-01-19 00:05:06
I tried without listen 80 but the problem is still there
2023-01-19 00:05:06
Even when listening on 443?
2023-01-19 00:05:06
Yep, starting to think the problem might be with cloudflare
2023-01-19 00:05:06
Have you tried to put this settings SECURE_SSL_REDIRECT in settings.py? This will force all the http requests to be https.
Answers(1) :

I ran into the same issue. And, it looks like, I found out why it doesn't work as expected.

Accordingly to the documentation, $scheme equals either http or https.

In the case of a location, which is declared in server that listens on 80 port, we get $scheme equal to http. Then, AFAIU, Django receives HTTP_X_FORWARDED_PROTO header which equals to http, and Django treats it as unsecured (i.e. request.is_secure() always returns False). Well, at least, it started to work well when I made the following change:

proxy_set_header X-Forwarded-Proto "https";