Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebSockets in Create React App with Webpack proxy

I created my React app using Create React App in version 3.1.2 (19 Sept 2019). I was trying to configure proxy for Web Socket requests, but it seems that when I am using the proxy, the connection is not established. I have used THIS example to set up my things. The server is Asp.Net Core as in example and it works as long as it has the address wired into the initalization. This snippet works:

const hubConnection = new HubConnectionBuilder()
  .withUrl("https://localhost:44392/chatHub")
  .build();

And this doesn't:

const hubConnection = new HubConnectionBuilder()
  .withUrl("chatHub")
  .build();

With this:

{
  "proxy": "https://localhost:44392/",
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@microsoft/signalr": "^3.0.0",
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
    "react-scripts": "3.1.2"
  },
(...)

I saw a suggestion HERE that I might use an object in proxy setup, but when I tried I got an error that proxy address has to be a single string, not an object:

 proxy: {
      '^/api': {
        target: '<url>',
        ws: true,
        changeOrigin: true
      },
      '^/foo': {
        target: '<other_url>'
      }
like image 382
mikes Avatar asked Sep 24 '19 21:09

mikes


3 Answers

For me, proxying a specific route under /api as a websocket route didn't worked with the previously suggested src\setupProxy.jsconfigurations.

But this works:

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
    app.use(
        createProxyMiddleware('/api',{
            target: 'http://localhost:9800',
            changeOrigin: true,
        })
    );

    app.use(
        createProxyMiddleware('/api/notification/register', {
            target: 'ws://localhost:9800',
            ws: true,
            changeOrigin: true,
        })
    );
};

And this actually produce a meaningful HPM output:

[HPM] Proxy created: /api  -> http://localhost:9800
[HPM] Proxy created: /api/notification/register  -> ws://localhost:9800
like image 87
khelkun Avatar answered Oct 17 '22 02:10

khelkun


Reposting a solution I posted here: https://github.com/facebook/create-react-app/issues/5280

I had a problem where I couldn't proxy requests (in development) to my own websocket (socket-io) server.

I followed the steps here: create-react-app proxying requests in dev, my setupProxy.js looked like this:

The below did not work for proxying a websocket connection:

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function (app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://localhost:5011',
    }),
  );
  app.use(
    '/socket-io',
    createProxyMiddleware({
      target: 'http://localhost:5011',
      ws: true,
    }),
  );
};

However, the hot reloading wouldn't work because somehow this interfered with webpack dev servers websocket connection. I would see this error in the console:

[HPM] Error occurred while trying to proxy request /sockjs-node from localhost:3000 to http://localhost:5011 (ECONNRESET) (https://nodejs.org/api/errors.html#errors_common_system_errors)

I got this working by doing the following:

const isDev = process.env.NODE_ENV === 'development';

const socket = isDev 
? io.connect('http://localhost:5011', { path: '/socket-io' }) 
: io.connect({ path: '/socket-io' });

Hope this helps someone out! Let me know if there's a better way to do this 👍

like image 35
neeko Avatar answered Oct 17 '22 03:10

neeko


After searching a bit, I finally found a solution https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually

First, install http-proxy-middleware. Next, create src/setupProxy.js and place the following contents in it:

const proxy = require('http-proxy-middleware');
module.exports = function(app) {
  app.use(
    '/api',
    proxy({
        target: '<url>',
        ws: true,
        changeOrigin: true
    })
  );
  app.use(
    '/foo',
    proxy({
        target: '<other_url>'
    })
  );
};
like image 27
Alexandre Avatar answered Oct 17 '22 01:10

Alexandre