2017-05-24 44 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頭的連接升級。當我更改爲不同的端口時,它工作正常。