【问题标题】:How to use Django Nginx Application with both HTTP and HTTPS requests?如何将 Django Nginx 应用程序与 HTTP 和 HTTPS 请求一起使用?
【发布时间】:2023-03-14 11:08:01
【问题描述】:

我有一个 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,但这不起作用

【问题讨论】:

  • 浏览器将阻止来自 https 页面的 http 请求...。您应该使用“url for”帮助程序或其他任何名称...或将其更改为url='/o/token/' ...但请查看http 重定向 nginx 以查看如何将 http 请求重写为 https ...
  • 当我尝试得到错误Invalid URL '/o/token/': No schema supplied. Perhaps you meant http:///o/token/。所以它不会自动添加主机和架构
  • 我也尝试使用 return 301 https://$host$request_uri; 将任何 http 请求转换为 Nginx 中的 https,但没有成功
  • 啊,你对 o/token 的事情是正确的...对不起,我想给予足够的关注...并且重定向可能会因发布数据而中断...。您为什么将其发布到 http?
  • @JoranBeasley 我可以直接 POST 到 HTTPS,但这只能在生产中使用。当我在本地主机上的开发中运行应用程序时,POST 到 HTTPS 将不起作用

标签: python django nginx https server


【解决方案1】:

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

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

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

【讨论】:

  • 是的,我可以这样做并且它有效,但是我在后端有几个这样的视图,必须这样做。我只是想知道是否可以对 Nginx 配置进行任何更改以解决我的问题?
  • @dracarys 查看编辑...如果您真的想这样做,我认为您可以这样做...。
  • 感谢您的帮助。我只是认为request.META['HTTP_HOST'] 确实保留了端口。 request.META['SERVER_NAME'] 不保留端口。请确认?
  • 大声笑我相信你... :)
猜你喜欢
  • 1970-01-01
  • 2016-10-28
  • 1970-01-01
  • 2017-09-10
  • 2020-02-15
  • 2019-01-24
  • 1970-01-01
  • 2013-05-27
  • 1970-01-01
相关资源
最近更新 更多