Django REST框架分页链接不使用HTTPS

Django REST框架分页链接不使用HTTPS,django,django-rest-framework,Django,Django Rest Framework,我正在为一个工作良好的特定DRF端点设置分页-但是,当部署到我的服务器(使用HTTPS)上时,到下一页和上一页的链接是用http://而不是HTTPS://形成的。这会导致浏览器阻止对下一页/上一页的请求 我已经仔细检查了最初的请求是否是用HTTPS发出的,第二个答复指出,由于请求是通过HTTPS发出的,所以应该在形成的URL中使用HTTPS 同一个问题的第一个答案也没有帮助——我将X-Forwarded-Proto行添加到我的nginx配置中,并重新加载,但没有效果 提到reverse()的行

我正在为一个工作良好的特定DRF端点设置分页-但是,当部署到我的服务器(使用HTTPS)上时,到下一页和上一页的链接是用
http://
而不是
HTTPS://
形成的。这会导致浏览器阻止对下一页/上一页的请求

我已经仔细检查了最初的请求是否是用HTTPS发出的,第二个答复指出,由于请求是通过HTTPS发出的,所以应该在形成的URL中使用HTTPS

同一个问题的第一个答案也没有帮助——我将
X-Forwarded-Proto
行添加到我的nginx配置中,并重新加载,但没有效果

提到reverse()的行为应该与基本的Django reverse相同,但是很明显,初始请求是HTTPS,而返回的URL是HTTP

以下是显示初始请求的两个屏幕截图(
https://.com/api/leaderboard/
):

响应包含
next:http://.com/api/leaderboard/?page=2
):

我想这将是一个简单的设置,但在搜索了这个站点和DRF站点之后,仍然找不到任何内容

这是我的nginx配置:

 location / {
    # proxy_pass http://127.0.0.1:9900;
    proxy_set_header X-Forwarded-Host $server_name;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"';

    root /opt/app/client/dist;
    index index.html index.htm;

}
包含一个非常详细的答案,但最终说URL是使用与请求相同的协议形成的,这里的情况似乎不是这样。我需要设置Django-SECURE\u-PROXY\u-SSL\u头吗?我不确定,因为警告说它可能不安全

我需要设置Django-SECURE\u-PROXY\u-SSL\u头吗?我不确定,因为警告说它可能不安全

是的,你知道。
然而,你需要注意你在做什么。特别是要确保它从外部删除X-Forwarded-Proto。

由于这是谷歌搜索结果中出现的第一篇SO帖子,我认为分享我是如何解决它的会很有用。我的有库伯内特斯的味道,但在引擎盖下,逻辑与其他的没有太大的不同

我使用的是坐在Django前面的Kubernetes ingress控制器,因此情况可能与您不同,但我将总结我的上下文,以便您可以看到它是否对您有用:

问题 因此,我遇到了与OP相同的问题,来自DRF的分页链接总是
http
,即使我使用
https
访问api端点。如果您设置了Django REST框架(DRF)附带的浏览器API,并转到API根页面,则可以更清楚地看到这一点。我看到所有由DRF生成的链接都是
http
,无论我在访问站点时使用什么协议

我的背景 从外部世界到Django的顺序:

  • Kuberenetes Nginx入口控制器(使用letsencrypt进行SSL设置)
  • 入口规则指向Django服务
  • Gunicorn启动Django服务器
  • Django读取
    settings.py
    并开始服务请求
  • 我如何调试并找出原因
  • 转储入口控制器的nginx.conf。如果您不知道如何实现这一点:首先通过
    kuberctl get pods-n
    算出pod名称,写下该名称,然后通过
    kubectl exec-it-n ingres\u controller\u命名空间ingres\u controller\u pod\u name cat/etc/nginx/nginx.conf>nginx.conf
    转储文件
  • 查看
    nginx.conf
    ,检查是否有
    proxy\u set\u头X-Forwarded-Proto$方案位置
    部分中的code>,或正确设置代理头
    X-Forwarded-Proto
    的类似内容。默认情况下,Kubernetes nginx ingress控制器应该已经为您准备好了这条线路(或等效线路)
  • 接下来,请求被定向到Gunicorn。一个问题是,您需要将
    --forwarded allow ips=“*”
    添加到您的gunicorn命令中,或者如果您知道您的nginx服务器IP,您可以限制到该IP,以便gunicorn为您转发头,否则gunicorn将删除这些头。因此,您最终得到的命令类似于
    gunicorn django\u server.wsgi:application--forwarded allow ips=“*”--workers=${property\u WORKER\u NUM}--log level info--bind 0.0.0.0:8001
    。通过指定
    workers=4
    ,可以有4个worker,这通常取决于服务器上的CPU。
    --log level info
    仅用于调试目的,是可选的
  • 在Django中,您需要在
    settings.py
    中有
    SECURE\u PROXY\u SSL\u HEADER=('HTTP\u X\u FORWARDED\u PROTO','https')
    ,其他答案也提到了这一点。您可能想知道,为什么在nginx中,前缀
    HTTP\uu
    的标题名是
    X-Forwarded-Proto
    。这是因为WSGI会将前缀添加到它识别的头中。这行基本上是说,如果头
    HTTP\u X\u-FORWARDED\u-PROTO
    等于字符串
    “https”
    ,那么Django会将请求识别为安全的。这将影响Django中的几个行为,例如,您将获得
    request.is\u secure==True
    request.build\u absolute\u uri(None)='https://...“
    ,最重要的是,Django REST框架分页链接现在将使用https
    !(只要您确实通过https
    https
    访问api)
  • 好的,现在你可以再次测试了。如果DRF现在给你https,恭喜你。或者,如果你和我一样,在尝试上面的内容后,仍然没有运气-DRF仍然生成该死的
    http
    链接。我想分享一些调试时的技巧:

    如果您拥有
    DEBUG=True
    并有权访问服务器日志,则可以通过
    Print()
    在Django中打印以下值,或者将其传递到模板上下文并在html页面中显示,如果这样可以更容易地在启用SSL的生产环境中进行测试

    • request.is\u secure()
      :如果您无法让DRF使用
      http
      ,那么您很可能会被删除