http-proxy-middleware: websocket proxy cannot upgrade websocket connection

Expected behavior

HPM should upgrade websocket requests always

Actual behavior

HPM websocket proxy cannot upgrade websocket connections sporadically

Setup

  • http-proxy-middleware: 0.17.1
  • server: tornado 4.4.1 - Tornado Github
  • webpack: 1.13.2
  • webpack-dev-server: 1.16.1

proxy middleware configuration

 devServer: {
      proxy: {
        '/hyperguard/websocket/*': {
          target: 'ws://localhost:8082',
        ws: true
        }
      }
    }

server mounting

def serve_forever(self):
    app = self.__make_app()
    self.__http_server = HTTPServer(app)
    self.__http_server._handle_connection = self._handle_connection
    self.__http_server.listen(self.__port, self.__host)
    app.ssl_enabled = self.__ssl_options is not None
    self.__ioloop.start()

Howto Reproduce

http stream request

GET /hyperguard/websocket HTTP/1.1
Host: localhost:8079
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
origin: http://localhost:8079
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Key: yrOcNHCvvVuGgttYgv9nzA==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

http stream response getting this response only sometimes, if not the websocket connection never be established

HTTP/1.1 101 Switching Protocols
upgrade: websocket
connection: Upgrade
sec-websocket-accept: I3u4B7iakSJWk4yLd02hfn+enus=
  • that issue also occurs on different platforms (fedora 22, ubuntu 14.04, centos7)
  • restarting webpack-dev-server doesnt change anything

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Comments: 20 (4 by maintainers)

Most upvoted comments

Apologies for commenting on an ancient ticket, but I managed to hit this issue (ws proxy only starts working after manually performing a GET call).

app.use(
    '/ws/live',
    createProxyMiddleware({
        target: process.env.API,
        ws: true, // enable websocket proxy
        changeOrigin: true,
        logLevel : 'debug'
    })
);

… “http-proxy-middleware”: “^1.0.6”, “react”: “^17.0.1”, “react-scripts”: “4.0.0”, …

I understand that no resolution was found, but does anyone know any workaround (better than manually doing a GET, I mean)?

I had problems with the proxy websocket closing right after connecting. Found out that socket io was closing unhandled requests. If you are using socket io, the fix is to set the destroyUpgrade option to false:

var express = require('express');
var app = express();
var http = require('http').Server(app);
var proxy = require('http-proxy-middleware');
var io = require('socket.io')(http, {destroyUpgrade: false});

debugged that problem weeks ago rudimentary, it seems that the http proxy middleware which is applied to the express server never be executed. maybe a side effect with sockjs which is used to handle the hot realoading websocket channel.

@torrejonv from my understanding it works like lazy loading. Until you make a request to the route where proxy middleware is registered there will be no “upgrade” handler added to the HTTP server. With this ☝️ approach, any request passes through the proxy middleware so that we have the “upgrade” handler registered from the very beginning.

Thank you for the explanation. Very ingenious indeed!

Direct connection

I think the issue is related to HPM, because if i request a websocket upgrade directly it always works as expected.

request (without HPM)

GET /hyperguard/websocket HTTP/1.1
Host: localhost:8082
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Sec-WebSocket-Version: 13
Origin: https://localhost:8082
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Key: 7XjMl4KmXDJa/TWfb7vabQ==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

immediatlely response (without HPM)

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: iC7Eh/cX6YgchA7mJQ950DWmIiQ=

Workaround

I figured out a way to reproduce a workaround with tornado + HPM + webpack-dev-server. If the problem occurs i just have to request the websocket proxy path via http e.g http://localhost:8079/hyperguard/websocket

response

HTTP/1.1 400 Bad Request
X-Powered-By: Express
Content-Length: 34
Date: Fri, 23 Sep 2016 09:13:38 GMT
Server: TornadoServer/4.4.1
Content-Type: text/html; charset=UTF-8
Connection: keep-alive

Can "Upgrade" only to "WebSocket".

If i go back to my working url e.g. http://localhost:8079 the websocket connection can be upgraded as expected.

Q&R

  • Adding changeOrigin option has no effect.
  • Tornado actually allows alternate origins.