2017-05-24 67 views
3

NGINX代理正在传递HTTP GET请求,而不是WebSocket握手到我的Django应用程序。码头NGINX代理不转发Websockets

事实:非WebSocket的代理到Django应用程序的

  • 其余的是伟大的工作。
  • 如果我直接连接到django应用程序容器,我可以让WebSockets工作。 (下面的相关日志条目。)
  • nginx配置在我的开发机器上运行localhost(无集装箱)。 (登录下面的例子。)

相关日志:绕过集装箱代理,并直接连接到服务器时

`xxx.xxx.xxx.xxx:40214 - - [24/May/2017:19:16:03] "GET /flight/all_flight_updates" 404 99` 

瑞香日志:

瑞香连接时通过集装箱nginx的代理登录:

xxx.xxx.xxx.xxx:6566 - - [24/May/2017:19:17:02] "WSCONNECTING /flight/all_flight_updates" - - 
xxx.xxx.xxx.xxx:6566 - - [24/May/2017:19:17:02] "WSCONNECT /flight/all_flight_updates" - - 

本地主机测试nginx(n上集装箱)配置工作:

[2017/05/24 14:24:19] WebSocket HANDSHAKING /flight/all_flight_updates [127.0.0.1:65100] 
[2017/05/24 14:24:19] WebSocket CONNECT /flight/all_flight_updates [127.0.0.1:65100] 

配置文件:

docker-compose.yml

version: '3' 
services: 
    db: 
    image: postgres 
    redis: 
    image: redis:alpine 
    web: 
    image: nginx 
    ports: 
    - '80:80' 
    volumes: 
    - ./deploy/proxy.template:/etc/nginx/conf.d/proxy.template 
    links: 
    - cdn 
    - app 
    command: /bin/bash -c "envsubst '' </etc/nginx/conf.d/proxy.template> /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" 
    cdn: 
    image: nginx 
    volumes: 
    - ./cdn_static:/usr/share/nginx/static 
    - ./deploy/cdn.template:/etc/nginx/conf.d/cdn.template 
    command: /bin/bash -c "envsubst '' </etc/nginx/conf.d/cdn.template> /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" 
    app: 
    build: . 
    image: app 
    ports: 
    - '8000:8000' 
    links: 
    - redis 
    - db 
    volumes: 
    - ./cdn_static:/var/static 

proxy.template NGINX配置模板:

upstream cdn_proxy { 
    server cdn:80; 
    } 

    upstream daphne { 
    server app:8000; 
    keepalive 100; 
    } 

    map $http_upgrade $connection_upgrade { 
     default upgrade; 
     ''  close; 
    } 

    server { 
    location /static { 
     proxy_pass http://cdn_proxy; 
    } 

    location/{ 
     proxy_buffering off; 
     proxy_pass http://daphne; 
     proxy_read_timeout  300; 
     proxy_connect_timeout 300; 

     proxy_http_version 1.1; 
     proxy_set_header Upgrade $http_upgrade; 
     proxy_set_header Connection $connection_upgrade; 

     proxy_redirect  off; 
     proxy_set_header Host $host; 
     proxy_set_header X-Real-IP $remote_addr; 
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
     proxy_set_header X-Forwarded-Host $server_name; 

    } 
    } 

UPDATE

我已经使用NGINX网站上的教程构建了一个更加简洁的问题示例,并将它放在github上的https://github.com/c0yote/nginx-websocket-issue

你得到426而不是404,但我相信这是因为简单的服务器不知道如何处理NGINX发送的GET。在这个想法中,我强化了这一点,如果你直接针对8000端口发出一个GET(例如从浏览器),你将得到相同的426.

因此,核心问题仍然是NGINX发送一个GET。

更多信息:

tcpdump表明GET到WebSocket的服务器有一个Upgrade场,但GET对NGINX没有。这是令人困惑的,因为wscat命令与目标端口的例外相同。

GIGA UPDATE:*

如果我参加了NGINX代理关闭80端口说,8080它的工作原理。我唯一的猜测就是js客户端对80端口做了一些假设。如果有人知道为什么会发生这种情况,我很想知道。

+0

你可以在容器通过'envsubst'运行后输出'/ etc/nginx/conf.d/default.conf'文件吗? –

+0

我已经通过docker exec在运行的容器上对它进行了检查,并且它是相同的。 –

回答

0

这是我的组织的防火墙。

它剥离了端口80上GET头的连接升级。当我更改为不同的端口时,它工作正常。