Как использовать приложение Django Nginx с HTTP и HTTPS запросами?
У меня есть веб-приложение, которое использует Django в качестве бэкенда и Nginx вместе с Gunicorn в качестве обратного прокси. Я уже настроил конфигурацию Nginx, и она отлично работает, когда запросы отправляются по HTTPS. Но при HTTP-запросах происходит сбой.
Я хочу, чтобы приложение работало для HTTP и HTTPS запросов.
Некоторые из моих представлений Django содержат внутренние запросы, которые выполняются по HTTP, так как они должны быть совместимы с сервером разработки и производственным сервером
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)
...
Моя конфигурация nginx следующая
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
}
Я разместил VPS на digital ocean.
Как заставить сервер работать и для http-запросов, которые выполняются внутренними представлениями бэкенда
Примечание: Я пытался перенаправить все HTTP запросы на HTTPS только на производстве в Nginx, сделав это return 301 https://$host$request_uri;
, но это не сработало
Я собираюсь пойти на хитрость и предположить, что вам на самом деле не нужно то, о чем вы просили... вместо этого вам просто нужно использовать ту же схему, которая также должна быть доступна в запросе
url = f"{request.scheme}://{request.META['HTTP_HOST']}/o/token"
примечание... что я не уверен на 100%, что это не сохранит порт (если это необходимо, это должно быть в META['SERVER_PORT']
)
в качестве альтернативы определите второй HTTP-сервер (убедитесь, что вы удалили :8000 из первого сервера)
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;
}
}
но я думаю, что это в целом считается плохой практикой