如何将 Django Nginx 应用程序与 HTTP 和 HTTPS 请求一起使用?

How to use Django Nginx Application with both HTTP and HTTPS requests?

我有一个 Web 应用程序,它使用 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 数字海洋。

如何使服务器也能处理由后端视图在内部发出的 http 请求

注意:我试图通过这样做 return 301 https://$host$request_uri; 将所有 HTTP 请求重定向到仅在 Nginx 生产环境中的 HTTPS,但这没有用

我要在这里冒险并假设您实际上并不想要您所要求的...相反,您只需要使用相同的架构,该架构也应该在请求中可用

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;
    }
}

但我认为这通常被认为是不好的做法