How to use Django Nginx Application with both HTTP and HTTPS requests?
I have a Web Application that uses Django as backend and Nginx along with Gunicorn for the reverse proxy. I have already set up the Nginx configuration and it works perfectly when requests are sent over HTTPS. But it fails when HTTP requests are made.
I want the application to work for both HTTP and HTTPS requests.
Some of my Django Views contain internal requests that are made over HTTP as they have to be compatible with the Development as well as Production Server
class LoginView(APIView):
...
http_host = request.META["HTTP_HOST"]
url = f"http://{http_host}/o/token/"
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
data = {
'username': req_data['username'],
'password': req_data['password'],
}
response = requests.post(url, headers=headers, data=data)
...
My nginx configuration is as follows
server {
listen 8000 ssl;
server_name backend.test.com www.backend.test.com;
access_log /var/log/nginx/app_backend.access.log;
error_log /var/log/nginx/app_backend.error.log;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/testuser/app_backend/app_backend;
}
location /media/ {
root /home/testuser/app_backend/app_backend;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/testuser/app_backend/app_backend/app_backend.sock;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/backend.test.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/backend.test.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
I have hosted the VPS on digital ocean.
How do I make the server work for http requests also that are made internally by the backend views
Note: I tried to redirect all HTTP request to HTTPS only in production in Nginx by doing this return 301 https://$host$request_uri;
, but that did not work
Solution 1:
Im going to go out on a limb here and assume you dont actually want what you asked for... instead you just need to use the same schema, which should be available in the request as well
url = f"{request.scheme}://{request.META['HTTP_HOST']}/o/token"
note... that Im not 100% sure this would not preserve the port (if needed it should be in META['SERVER_PORT']
)
alternatively define a second HTTP server (make sure you remove the :8000 from the first server)
server {
listen 8000 80;
server_name backend.test.com www.backend.test.com;
access_log /var/log/nginx/app_backend.access.log;
error_log /var/log/nginx/app_backend.error.log;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/testuser/app_backend/app_backend;
}
location /media/ {
root /home/testuser/app_backend/app_backend;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/testuser/app_backend/app_backend/app_backend.sock;
}
}
but i think this is generally deemed bad practice