我一直试图让Nginx的WebSocket代理在过去的几天工作,但对我来说,我无法得到它的工作。 我遵循这里的官方指南,并使用Python的websockets
模块作为服务器,并使用npm包作为客户端。 从wscat
直接连接到Python WebSocket后端工作正常(从浏览器连接也是如此)。 但是,只要我在Nginx中进行分层,它就不能正常工作,并继续给我一个标准的HTTP 301redirect。
使用Nginx代理的cURLdebugging输出:
$ curl 'http://test.ws:8080/websocket' \ > -H 'Pragma: no-cache' \ > -H 'Origin: http://localhost:8080' \ > -H 'Accept-Encoding: gzip, deflate, sdch' \ > -H 'Sec-WebSocket-Version: 13' \ > -H 'Sec-WebSocket-Key: V15bszpaQ+8Vq7mWR6NQbQ==' \ > -H 'User-Agent: Mozilla/5.0' \ > -H 'Upgrade: websocket' \ > -H 'Cache-Control: no-cache' \ > -H 'Connection: Upgrade' \ > -H 'Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits' \ --compressed -v * Hostname was NOT found in DNS cache * Trying 127.0.0.1... * Connected to test.ws (127.0.0.1) port 8080 (#0) > GET /websocket HTTP/1.1 > Host: test.ws:8080 > Accept: */* > Pragma: no-cache > Origin: http://localhost:8080 > Accept-Encoding: gzip, deflate, sdch > Sec-WebSocket-Version: 13 > Sec-WebSocket-Key: V15bszpaQ+8Vq7mWR6NQbQ== > User-Agent: Mozilla/5.0 > Upgrade: websocket > Cache-Control: no-cache > Connection: Upgrade > Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits > < HTTP/1.1 301 Moved Permanently * Server nginx/1.8.0 is not blacklisted < Server: nginx/1.8.0 < Date: Mon, 10 Aug 2015 15:04:26 GMT < Content-Type: text/html < Content-Length: 184 < Location: http://test.ws:8080/websocket/ < Connection: keep-alive < <html> <head><title>301 Moved Permanently</title></head> <body bgcolor="white"> <center><h1>301 Moved Permanently</h1></center> <hr><center>nginx/1.8.0</center> </body> </html> * Connection #0 to host test.ws left intact
没有 Nginx代理的cURLdebugging输出:
$ curl 'http://test.ws:8765/' \ > -H 'Pragma: no-cache' \ > -H 'Origin: http://localhost:8080' \ > -H 'Accept-Encoding: gzip, deflate, sdch' \ > -H 'Sec-WebSocket-Version: 13' \ > -H 'Sec-WebSocket-Key: V15bszpaQ+8Vq7mWR6NQbQ==' \ > -H 'User-Agent: Mozilla/5.0' \ > -H 'Upgrade: websocket' \ > -H 'Cache-Control: no-cache' \ > -H 'Connection: Upgrade' \ > -H 'Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits' \ > --compressed -v * Hostname was NOT found in DNS cache * Trying 127.0.0.1... * Connected to test.ws (127.0.0.1) port 8765 (#0) > GET / HTTP/1.1 > Host: test.ws:8765 > Accept: */* > Pragma: no-cache > Origin: http://localhost:8080 > Accept-Encoding: gzip, deflate, sdch > Sec-WebSocket-Version: 13 > Sec-WebSocket-Key: V15bszpaQ+8Vq7mWR6NQbQ== > User-Agent: Mozilla/5.0 > Upgrade: websocket > Cache-Control: no-cache > Connection: Upgrade > Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits > < HTTP/1.1 101 Switching Protocols * Server Python/3.4 websockets/2.5 is not blacklisted < Server: Python/3.4 websockets/2.5 < Upgrade: WebSocket < Connection: Upgrade < Sec-WebSocket-Accept: yR97tmHAm9KPEI5vfKiM0/sfTqQ= ^C
我的Nginx(版本1.8.0
)configuration是这样的(在8765端口上运行在test.ws(127.0.0.1)上的websockets)和nginx正在侦听localhost上的8080端口:
worker_processes 1; error_log logs/error.log debug; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; upstream ws { server 127.0.0.1:8765; } # map $http_upgrade $connection_upgrade { # default upgrade; # '' close; # } server { listen 8080; server_name test.ws; access_log logs/localhost.access.log; location / { root html; index index.html index.htm; } location /websocket/ { proxy_pass http://ws; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } } include servers/*;
任何人都知道我在这里做错了什么,为什么它给了我301redirect?
事实证明,我的Nginx配置中的根位置节已经干扰了WebSocket代理传递隧道。 有三种方法可以解决这个问题。
修改根位置节完全匹配。
location = / { root html; index index.html index.htm; }
重新排序根节点websocket
之后的websocket
位置节(特定的第一个,一般的最后,就像重写匹配规则的工作原理)。
在Nginx配置中删除以下根位置节将使其工作。
location / { root html; index index.html index.htm; }
注意你的标题。 在Web浏览器和客户端发送的头文件中, Upgrade
不upgrade
。
改变这个:
location /websocket/ { proxy_pass http://ws; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
至
location /websocket/ { proxy_pass http://ws; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; }
注意大写Upgrade