Node.js 节点、ws、ssl、nginx给出错误426,需要升级
我正在使用Node.js和NGINX为一个应用程序提供服务。我正在使用LetsEncrypt保护NGINX,并使用pm2在服务器上运行我的节点应用程序(使用NGINX作为反向代理) 我的站点不会加载任何内容(426错误-需要升级),但我可以使用以下草稿行进行连接:Node.js 节点、ws、ssl、nginx给出错误426,需要升级,node.js,nginx,websocket,Node.js,Nginx,Websocket,我正在使用Node.js和NGINX为一个应用程序提供服务。我正在使用LetsEncrypt保护NGINX,并使用pm2在服务器上运行我的节点应用程序(使用NGINX作为反向代理) 我的站点不会加载任何内容(426错误-需要升级),但我可以使用以下草稿行进行连接: var port = 443; var ws = new WebSocket("wss://mywebsite.com:" + port); ws.onopen = function() { console.log("Conne
var port = 443;
var ws = new WebSocket("wss://mywebsite.com:" + port);
ws.onopen = function() {
console.log("Connected");
}
ws.onmessage = function(comment) {
console.log(JSON.parse(comment.data));
}
以下是NGINX设置:
server {
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name mywebsite.com www.mywebsite.com;
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /path/to/cert; # managed by Certbot
ssl_certificate_key /path/to/key; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.mywebsite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = mywebsite.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name mywebsite.com www.mywebsite.com;
return 404; # managed by Certbot
}
我的客户端代码与scratchpad基本相同。这是相关的服务器端代码:
var WebSocket = require('ws');
var serverPort = 8080;
var wss = new WebSocket.Server({port:serverPort});
console.log("Server running on port " + serverPort + " started at: " + new Date());
wss.on('connection', function(ws) {
console.log("Connected to websocket: " + ws);
var introComment = JSON.stringify({
user: "Welcome!",
data: {
body: "Welcome to the realtime feed!",
name: "realtime-intro-connection-message",
},
});
ws.send(introComment);
});
以下是浏览器收到的响应标题:
HTTP/1.1 426 Upgrade Required
Server: nginx/1.10.3 (Ubuntu)
Date: Wed, 23 May 2018 19:20:36 GMT
Content-Type: text/plain
Content-Length: 16
Connection: keep-alive
我读到应该有一个“升级”标题,这是问题的一部分吗?我从未真正找到这个问题的答案,所以我改变了策略:
我从ws(npm的WebSocket)迁移到socket.io。这似乎得到了更广泛的支持。对于使用socket.io的示例应用程序,请看这些精彩的视频!现在一切正常。要将客户端和服务器之间的连接从HTTP/1.1转换为WebSocket,需要使用HTTP/1.1中可用的协议切换机制 然而,有一个微妙之处:因为“升级”是一个逐跳的头,所以它不会从客户端传递到代理服务器。使用前向代理,客户端可以使用CONNECT方法来避免此问题。但是,这不适用于反向代理,因为客户端不知道任何代理服务器,并且需要在代理服务器上进行特殊处理 自1.3.13版以来,nginx实施了特殊的操作模式,如果代理服务器返回代码为101(交换协议)的响应,并且客户端通过请求中的“升级”头请求协议切换,则允许在客户端和代理服务器之间建立隧道 如上所述,包括“升级”和“连接”在内的逐跳标头不会从客户端传递到代理服务器,因此,为了让代理服务器了解客户端将协议切换到WebSocket的意图,必须显式传递这些标头:
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
一个更复杂的示例,其中到代理服务器的请求中的“连接”标头字段的值取决于客户端请求标头中是否存在“升级”字段:
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
服务器{
location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
也许您需要将:proxy\u http\u version 1.1;更改为更高版本?这似乎是@nginx official的推荐版本(只有1.0和1.1):您的nodejs服务器正在发送的http版本是什么?