How to make WebSocket work with proxy settings?

See original GitHub issue

I try to proxy my websocket in dev mode using the manual proxy as described in the documentation https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually

In my src/setupProxy.js I have the following code:

const proxy = require('http-proxy-middleware');
module.exports = function (app) {
    app.use(
        proxy('/isomor', {
            target: 'http://127.0.0.1:3005',
            ws: true,
        }),
    );
};

But when I try to connect, the connection get disconnected directly:

[HPM] GET /isomor -> http://127.0.0.1:3005
[HPM] Upgrading to WebSocket
[HPM] Client disconnected

When you look at the documentation of http-proxy-middleware they requiere server.on('upgrade', wsProxy.upgrade);, see https://github.com/chimurai/http-proxy-middleware#external-websocket-upgrade Or the http server is not available in setupProxy.js

Did someone already manage to proxy websocket with create-react-app?


Edit

After debugguing the code for hours, I get the following error from http-proxy:

Error [ERR_STREAM_DESTROYED]: Cannot call write after a stream was destroyed
    at doWrite (_stream_writable.js:431:19)
    at writeOrBuffer (_stream_writable.js:419:5)
    at Socket.Writable.write (_stream_writable.js:309:11)
    at ClientRequest.<anonymous> (/home/alex/dev/node/pkg/isomor/packages/example/react/node_modules/http-proxy/lib/http-proxy/passes/ws-incoming.js:157:14)
    at ClientRequest.emit (events.js:223:5)
    at Socket.socketOnData (_http_client.js:490:11)
    at Socket.emit (events.js:223:5)
    at addChunk (_stream_readable.js:309:12)
    at readableAddChunk (_stream_readable.js:290:11)
    at Socket.Readable.push (_stream_readable.js:224:10)
    at TCP.onStreamRead (internal/stream_base_commons.js:181:23) {
  code: 'ERR_STREAM_DESTROYED'

It seem that server.on('upgrade', wsProxy.upgrade); is done by http-proxy-middleware inside the middleware with req.connection.server. But I wonder if this server is the one expected by http-proxy. When I try to instanciate my own websocket server I get some similar STREAM issue:

const proxy = require('http-proxy-middleware');
const WebSocket = require('ws');

let wss;
module.exports = function (app, server) {
    app.use('/test', (req, res, next) => {
        const { server } = req.connection;
        if (!wss) {
            wss = new WebSocket.Server({ server });
        }
        next();
    });
};

With this code I get the following error:

events.js:200
      throw er; // Unhandled 'error' event
      ^

Error [ERR_STREAM_WRITE_AFTER_END]: write after end
    at writeAfterEnd (_stream_writable.js:257:14)
    at Receiver.Writable.write (_stream_writable.js:306:5)
    at Socket.socketOnData (/home/alex/dev/node/pkg/isomor/packages/example/react/node_modules/ws/lib/websocket.js:864:35)
    at Socket.emit (events.js:228:7)
    at addChunk (_stream_readable.js:309:12)
    at readableAddChunk (_stream_readable.js:290:11)
    at Socket.Readable.push (_stream_readable.js:224:10)
    at TCP.onStreamRead (internal/stream_base_commons.js:181:23)
Emitted 'error' event on WebSocket instance at:
    at Receiver.receiverOnError (/home/alex/dev/node/pkg/isomor/packages/example/react/node_modules/ws/lib/websocket.js:769:13)
    at Receiver.emit (events.js:223:5)
    at errorOrDestroy (internal/streams/destroy.js:108:12)
    at writeAfterEnd (_stream_writable.js:259:3)
    at Receiver.Writable.write (_stream_writable.js:306:5)
    [... lines matching original stack trace ...]
    at TCP.onStreamRead (internal/stream_base_commons.js:181:23) {
  code: 'ERR_STREAM_WRITE_AFTER_END'

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
codercodingthecodecommented, Feb 4, 2020

That is the old version of cra, since 2.x it has it built-in. In my case, I get a similar proxy error with the latest cra when using this lib. image

1reaction
chybisovcommented, Feb 5, 2020

I have similar issue, this middleware works weird, it is somehow trying to proxy websocket sockjs-node request from webpackDevServer to my api server and I have these errors

image image

  app.use('/ws', proxy({
    target: 'SOME_API',
    changeOrigin: true,
    ws: true,
    secure: false,
    logLevel: 'debug'
  }));

So if I have two WS connections and one of them has proxy then webpack also proxy his sockjs-node to that server, but it shouldn’t do this.

UPDATE: I figured out how it actually works for me without proxying WebpackDevServer sockjs-node.

  app.use('/ws', proxy('/ws', {
    target: 'SOME_API',
    changeOrigin: true,
    ws: true,
    secure: false,
    logLevel: 'debug'
  }));

We need first '/ws' for

Mounts the specified middleware function or functions at the specified path: the middleware function is executed when the base of the requested path matches path. From Express documentation.

And we need second '/ws' to specify context for http-proxy-middleware. If we skip this parameter then context is / and all websocket connections proxying to specified target option.

Now it works like a charm. Hope it helps someone. 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

Websockets not connected behind proxy - Stack Overflow
This is a common issue (some cell-phone companies have proxies that disrupt websocket connections) and the solution is to use TLS/SSL ...
Read more >
How HTML5 Web Sockets Interact With Proxy Servers - InfoQ
When a proxy server forwards a request to the (WebSocket) server, it is expected to strip off certain headers, including the Connection header....
Read more >
WebSocket over a Forward Proxy - Software AG Documentation
WebSocket communication can take successfully take place in the presence of forward proxies, providing the client and proxy server have been configured properly ......
Read more >
Reverse HTTP proxy over WebSocket in Go (Part 1)
A reverse HTTP proxy over WebSocket is a type of proxy server which uses the WebSocket protocol as a "tunnel" to pass TCP...
Read more >
Using NGINX as a WebSocket Proxy
Here is a live example to show NGINX working as a WebSocket proxy. This example uses ws, a WebSocket implementation built on Node.js....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found