NGINX代理将HTTP GET请求而不是WebSocket握手传递给我的django应用程序 .
Facts:
-
其余的非websocket代理到django应用程序工作得很好 .
-
如果我直接连接到django应用程序容器,我可以使WebSockets工作 . (下面的相关日志条目 . )
-
nginx配置在我的开发机器上运行localhost(没有容器化) . (下面的日志示例 . )
Relevant Logs:
通过容器化nginx代理连接时的Daphne日志:
`xxx.xxx.xxx.xxx:40214 - - [24/May/2017:19:16:03] "GET /flight/all_flight_updates" 404 99`
Daphne在绕过容器化代理并直接连接到服务器时进行日志记录:
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(非容器化)配置的localhost测试工作:
[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]
Configuration files:
我的 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网站上的教程构建了一个更紧凑的问题示例,并将其放在https://github.com/c0yote/nginx-websocket-issue的github上 .
你得到426而不是404,但我相信这是因为简单的服务器不知道如何处理NGINX发送的GET . 我在这个想法中得到了加强,因为如果你直接针对8000端口发出GET(例如从浏览器),你会得到相同的426 .
因此核心问题仍然是NGINX正在发送GET .
MORE INFO:
tcpdump
表明websocket服务器的 GET
有一个 Upgrade
字段,但针对NGINX的 GET
没有 . 这是令人困惑的,因为 wscat
命令与目标端口的例外相同 .
GIGA UPDATE:*
如果我从端口80关闭NGINX代理,8080它可以工作 . 我唯一的猜测是,js客户端对端口80做了一些假设 . 如果有人知道为什么会这样,我很想知道 .
1 回答
这是我组织的防火墙 .
它正在从端口80上的GET标头中剥离连接升级 . 当我更改为其他端口时,它工作正常 .