lwsjs / local-web-server

A lean, modular web server for rapid full-stack development.
MIT License
1.2k stars 85 forks source link

add support for proxying websockets #126

Open 5im-0n opened 4 years ago

5im-0n commented 4 years ago

When proxying a websocket with --rewrite '/ws/(.*) --> https://someserver.com/ws/$1' local-web-server somehow mangles the response.

75lb commented 4 years ago

lws-rewrite does not currently support rewriting Websocket requests (which can only be proxied via HTTP Connect tunnelling) but i've starting looking for a solution which also honours corporate HTTP proxies.

tiagostutz commented 4 years ago

Hi! Still needing some help with this? If so, do you have any contributing guidelines or something like this?

We are adopting Open Source Friday here at Banco do Brasil and I can take this one on my Open Source Fridays.

75lb commented 4 years ago

Yes, help welcome thanks.. I should write some contributing guidelines - will add it to my list, thanks.

donald-stolz commented 1 year ago

Any update on this issue? I recently ran into it as well

svercammen commented 8 months ago

I solved the issue of forwarding a Next.JS HRM websocket connection by writing some middleware in file proxy/mw-websocket.mjs:

import { WebSocket, WebSocketServer } from 'ws';

const HMR_PATH = '_next/webpack-hmr';

class Websocket {
  middleware(config, lws) {
    const wss = new WebSocketServer({ server: lws.server, path: `/${HMR_PATH}` });

    wss.on('connection', (serverSocket) => {
      const target = `${config.wsRewrite}/${HMR_PATH}`;
      console.log(`WebSocket connection opened; forwarding to ${target}`);

      const clientSocket = new WebSocket(target);
      clientSocket.on('message', (message) => {
        // console.log(`Received from upstream: ${message}`);
        serverSocket.send(message.toString());
      });

      serverSocket.on('message', (message) => {
        // console.log(`Received from browser: ${message}`);
        clientSocket.send(message.toString());
      });
    });
  }
}

export default Websocket;

Configure it as follows. Target address in in property wsRewrite and don't forget to include the middleware in the stack. The stack following the middleware is the default stack, feel free to adjust to your needs:

module.exports = {
  [... your other configuration],
  wsRewrite: 'ws://localhost:4200',
  stack: [
    'proxy/mw-websocket.mjs',
    'lws-body-parser',
    'lws-request-monitor',
    'lws-log',
    'lws-cors',
    'lws-json',
    'lws-rewrite',
    'lws-blacklist',
    'lws-conditional-get',
    'lws-mime',
    'lws-compress',
    'lws-spa',
    'lws-static',
    'lws-index',
  ],
};

Note that this only forwards connections to one specific path and performs absolutely zero error checks, which is fine for my application. Ideally this use case would at some point be supported but for now this is a functioning workaround.