简体   繁体   English

使用SSL,AWS Load Balancer,Nginx和Gunicorn的具有复杂堆栈的Dja​​ngo Rest Framework错误的超链接

[英]Wrong hyperlinks of Django Rest Framework with complex stack using SSL, AWS Load Balancer, Nginx and Gunicorn

I can't find out how to correctly set up nginx so my hyperlinks in API build by DRF are correct. 我找不到如何正确设置nginx因此我在DRF构建的API中的超链接是正确的。

My current configuration for nginx is: 我当前对nginx配置是:

upstream web {
  ip_hash;
  server web:8000;
}

# portal
server {
  listen 8000;
  server_name localhost;

  location / {
        proxy_set_header        Host $host:$server_port;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto $scheme;
        proxy_pass http://web/;
    }
}

nginx is running inside a container exposing port 8000 and maps it into internally running gunicorn (also in a container) also on 8000 . nginx是在容器内运行暴露端口8000和地图入内部运行gunicorn(也在容器中)也在8000 So when I spin up the whole docker machinery, I can nicely access localhost:8000/api and links are rendered OK. 因此,当我启动整个docker机械时,我可以很好地访问localhost:8000/api并且链接呈现为OK。 Even when I access it using different domain (eg if I set in /etc/hosts : 127.0.0.1 mytest.com ), the URL and port get passed correctly to the DRF and links are rendered as expect. 即使当我使用其他域访问它时(例如,如果我在/etc/hosts127.0.0.1 mytest.com ),URL和端口127.0.0.1 mytest.com正确传递到DRF,并且链接将按预期方式呈现。

But this service must sit behind AWS Load Balancer with certificate using SSL. 但是此服务必须位于具有SSL证书的AWS Load Balancer后面。 Hostname on this LB is set otherdomain.com and it redirects traffic to the machine where the above nginx is run using HTTP on port 8000. Then, when try to access it using https://otherdomain.com/api , links are rendered as http://otherdomain.com:8000/api/ <- hence wrong scheme (http instead https) and wrong port (8000 instead of 80/443). 该LB上的主机名设置为otherdomain.com ,它将流量重定向到使用端口8000上的HTTP在上面运行nginx的计算机。然后,当尝试使用https://otherdomain.com/api访问它时,链接呈现为http://otherdomain.com:8000/api/ <-因此使用了错误的scheme (用HTTP代替https)和错误的端口(用8000代替了80/443)。 It make sense, since nginx doesn't know anything about the original request coming to load balancer... 这是有道理的,因为nginx对到达负载均衡器的原始请求一无所知...

None of the ideas I could think of sounds correct. 我无法想到的任何想法听起来都是正确的。 Would greatly appreciate any help. 将不胜感激任何帮助。 I am willing to change the infrastructure of course. 我当然愿意改变基础架构。

Any idea how can this be solved? 知道如何解决吗?

Add to your settings.py . 添加到您的settings.py

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
SECURE_SSL_REDIRECT = not DEBUG

Edit by kotrfa: relevant part of documentation . 由kotrfa编辑: 文档的相关部分 I didn't want to add the second line, so it was still possible to access the server directly without HTTPS, eg when testing on localhost. 我不想添加第二行,因此仍然可以在没有HTTPS的情况下直接访问服务器,例如在localhost上进行测试时。 For that, I had to set up two different servers in nginx - one with hardcoded Host my.domain.org on the same port coming from load balancer (eg 7779) and then a second with Host $host:$port on 7778 so it could be accessed directly behind VPN or on localhost and links still works :-) . 为此,我必须在nginx设置两台不同的服务器-一台在负载均衡器(例如7779)来自同一端口上的硬编码Host my.domain.org ,然后一台在7778上使用Host $host:$port可以直接在VPN后面或在localhost上访问,并且链接仍然有效:-)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM