在过去的几天里,我一直在尝试让Nginx WebSocket代理正常工作,但是对于我一生来说,我无法使其正常工作.我遵循官方指南here,一直使用Python的websockets模块作为服务器,并使用npm软件包wscat作为客户端.从wscat到Python WebSocket后端的直接连接工作正常(来自浏览器的连接也是如此).但是,一旦我在Nginx中分层,它就无法正常工作,并继续为我提供标准的HTTP 301重定向.
使用Nginx代理进行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,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代理的cURL调试输出:
$curl 'http://test.ws:8765/'
> -H 'Pragma: no-cache'
> -H 'Origin: http://localhost:8080'
> -H 'Accept-Encoding: gzip,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,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)配置是这样的(websockets运行在端口8765的test.ws(127.0.0.1)上),并且nginx正在本地主机的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重定向?
事实证明,我的Nginx配置中的根位置节一直在干扰WebSocket代理传递隧道.有三种方法可以解决此问题.
>修改根位置节以完全匹配.
location = / {
root html;
index index.html index.htm;
}
>将根位置节重新排序为websocket位置节之后(首先是特定的,最后是普通的,就像重写匹配规则如何工作一样).
>在Nginx配置中删除以下根位置节将使其起作用.
location / {
root html;
index index.html index.htm;
}