Nginx WebSocket代理不断获得HTTP 301redirect

我一直试图让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代理传递隧道。 有三种方法可以解决这个问题。

  1. 修改根位置节完全匹配。

     location = / { root html; index index.html index.htm; } 
  2. 重新排序根节点websocket 之后websocket位置节(特定的第一个,一般的最后,就像重写匹配规则的工作原理)。

  3. 在Nginx配置中删除以下根位置节将使其工作。

     location / { root html; index index.html index.htm; } 

注意你的标题。 在Web浏览器和客户端发送的头文件中, Upgradeupgrade

改变这个:

  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