Spring WebSocket:握手失败,原因是无效的升级标头:null。

37

我正在使用Spring后端的wss(安全Web套接字),并且使用STOMP来为JavaScript客户端提供支持。

请问有人知道为什么会得到以下错误:

Handshake failed due to invalid Upgrade header: null

你能提供更多细节吗?Spring 版本是多少?你的 Web 配置是什么?你是否使用了 SockJS?你能复制/粘贴请求和响应头吗? - Brian Clozel
将来参考,当我们遇到“握手失败”问题时,我们还在后端 (JBoss 7.1.6 GA + Spring 5.2.7.RELEASE) 上遇到了一个 HTTP 连接泄漏问题,您可以通过监视 JBoss CLI 中 /subsystem=io/worker=default/server=/127.0.0.1:6080connection-count 找到。 简单地应用 http://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html 的建议来“同时代理 HTTP 和 WebSockets”,使得两个错误日志和泄漏问题都消失了。 - Romain Buquet
5个回答

48

我遇到了与nginx https代理到tomcat相同的问题。这是因为我没有支持wss请求。为了支持wss请求,我使用了以下配置:

# WebSocketSecure SSL Endpoint
#
# The proxy is also an SSL endpoint for WSS and HTTPS connections.
# So the clients can use wss:// connections 
# (e.g. from pages served via HTTPS) which work better with broken 
# proxy servers, etc.

server {
    listen 443;

    # host name to respond to
    server_name ws.example.com;

    # your SSL configuration
    ssl on;
    ssl_certificate /etc/ssl/localcerts/ws.example.com.bundle.crt;
    ssl_certificate_key /etc/ssl/localcerts/ws.example.com.key;

    location / {
        # switch off logging
        access_log off;

        # redirect all HTTP traffic to localhost:8080
        proxy_pass http://localhost:8080;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # WebSocket support (nginx 1.4)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

3
看起来我面临着相同的问题。这个配置应该放在哪里? - Artyom Emelyanenko
我遇到了相同的问题,但我的URL是ws://localhost:8070/gs-guide-websocket/518/ufd3l0ca/websocket。我已经为ws请求添加了对端口8070的支持。请@Jonguo帮忙。 - haripcce
抱歉,我不记得如何解决了,很久没有登录StackOverflow了。升级你的Nginx和Tomcat,也许会起作用。现在我正在使用Golang,我没有使用Tomcat。抱歉。 - Jonguo

3
以下解决方案对我有效。
<VirtualHost _default_:443>
    
    ServerName my.app
    ServerAdmin admin@my.app
    DocumentRoot /var/www/html
    SSLCertificateFile ...
    SSLCertificateKeyFile ...
    SSLCertificateChainFile ...
    
    ProxyPreserveHost on
    RequestHeader set X-Forwarded-Proto https
    RequestHeader set X-Forwarded-Port 443
    
    RewriteEngine on
    RewriteCond %{HTTP:Upgrade}^websocket$ [NC,OR]
    RewriteCond %{HTTP:Connection}^upgrade$ [NC]
    RewriteRule .* wss:/127.0.0.1:8081%{REQUEST_URI} [P,QSA,L]
    RewriteCond %{REQUEST_URI} ^/api/wsendpoint/%{var1}/%{var2}/websocket [NC,OR]

    ....
    
</VirtualHost>

我希望这可以帮助到您... 上面的解决方案是以下链接的一部分: https://forum.mattermost.org/t/solved-apache2-reverseproxy-with-websocket-https/437/3


1
这篇帖子似乎已经关闭,但是我在这里没有找到确切的解决方案,所以我将为未来的需求发布。
我通过反向代理配置(在我的情况下是apache httpd)解决了这个问题。
首先,您需要在httpd.conf中启用一些模块。
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule rewrite_module modules/mod_rewrite.so

然后进入您的虚拟主机配置,并使用这些规则。

RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule /(.*) "ws://[YOUR_URL]:[YOUR_PORT]/$1" [P,L]

显然,将[YOUR_URL]和[YOUT_PORT]替换为实际的url和端口,并且如果您正在使用安全的Web套接字,则将“ws”替换为“wss”。

就这样!

如果您在服务器上做了正确的事情,您可以阅读以下标题。

upgrade: WebSocket
connection: Upgrade

0

DefaultHandshakeHandler - "握手失败,原因是无效的升级头: null"

这里的URL应该包含端口号

例如:ws://或wss://{baseUrl}:8080/您的WebSocket端点

并在服务器上使用以下命令启用代理

$ sudo a2enmod proxy
$ sudo service apache2 restart
$ sudo a2enmod proxy_wstunnel
$ sudo service apache2 restart

你可以阅读这篇文章https://github.com/spring-projects/spring-framework/issues/16978#issuecomment-453418847


0
我在使用Kotlin + SpringBootTest测试WebSocket时遇到了相同的错误信息。
错误提示说,我忘记添加名为"Upgrade"和其他ws-headers的HttpHeader。
我使用了这些头部信息,问题就解决了:
        val headers = HttpHeaders()
        headers["Upgrade"] = listOf("websocket")
        headers["Connection"] = listOf("Upgrade")
        headers["Sec-WebSocket-Version"] = listOf("13")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接