我一直试图让Nginx WebSocket代理在过去几天工作,但对于我的生活,我无法让它工作。我遵循了官方指南here并且一直使用Python的websockets
模块作为服务器,使用npm包wscat
作为客户端。从wscat
到Python WebSocket后端的直接连接工作正常(来自浏览器的连接也是如此)。但是一旦我在Nginx中进行分层,它就无法正常工作并继续给我一个标准的HTTP 301重定向。
cURL调试输出:
$ 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
cURL调试输出没有 Nginx代理:
$ 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
)配置是这样的(在端口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/*;
任何人都知道我在这里做错了什么,为什么它给我301重定向?
答案 0 :(得分:2)
事实证明,我的Nginx配置中的根位置节干扰了WebSocket代理传递隧道。有三种方法可以解决这个问题。
修改根位置节以完全匹配。
location = / {
root html;
index index.html index.htm;
}
在 websocket
位置节之后将根位置节重新排序为(首先是特定的节点,最后的节点节点,就像重写匹配规则的工作原理一样)。 / p>
在Nginx配置中删除以下根位置节将使其正常工作。
location / {
root html;
index index.html index.htm;
}
答案 1 :(得分:1)
注意标题。在网络浏览器和客户端发送的标头中,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
答案 2 :(得分:1)
在我的情况下,它来自客户端,使用路径/ websocket而不是/ websocket /,从而阻止了位置规则的出现。 但是位置顺序的影响是一个很好的提示!