NGINX not passing headers to websocket endpoint

2019-05-23 22:09发布

问题:

I am trying to configure nginx as reverse proxy that does authentication and websockets. It proxy-passes request to apache (/auth/wsgi) for authentication - once that succeeds, it then proxy passes to the websocked backend, which is a java based websocket endpoint on tomcat 8.

location /basic/alerting/websocket {
    auth_request /auth/wsgi;
    proxy_pass http://backend.com:8080/websocket;
    proxy_http_version 1.1;
    proxy_set_header Upgrade "Websocket";
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $http_host;
}

The authentication on apache succeeds. However, on the backend tomcat, I get this error:

12572237 [http-nio-8080-exec-10] ERROR org.springframework.web.socket.server.support.DefaultHandshakeHandler - handleWebSocketVersionNotSupported() Handshake failed due to unsupported WebSocket version: null. Supported versions: [13]

It seems that failure is because the backend is expecting the header ("Sec-WebSocket-Version") which is not getting passed through. I even see in the nginx logs:

2015/03/17 17:28:12 [debug] 20261#0: *718 http proxy header: "Sec-WebSocket-Version: 13"

Is there anything I need to do in the nginx config? Very much appreciate your help.

回答1:

The problem is that Nginx doesn't pass all the "Sec-WebSocket-*" headers. Then the method AbstractHandshakeHandler.java#handleWebSocketVersionNotSupported() will throw the exception.

The fix is that Nginx to copy all the "Sec-WebSocket-*" headers. Request headers: Sec-WebSocket-Extensions, Sec-WebSocket-Key, Sec-WebSocket-Protocol, Sec-WebSocket-Version Response headers: Sec-WebSocket-Accept, Sec-WebSocket-Extensions, Sec-WebSocket-Protocol

To copy a custom Nginx header you need to do something like this:

proxy_set_header Sec-WebSocket-Protocol $http_sec_websocket_protocol