在 create-react-app 中使用 Socket.io-client 的 WebSockets 代理

Posted

技术标签:

【中文标题】在 create-react-app 中使用 Socket.io-client 的 WebSockets 代理【英文标题】:WebSockets Proxy using Socket.io-client in create-react-app 【发布时间】:2020-08-22 02:35:41 【问题描述】:

我正在尝试为 socket.io-client 的 React 应用添加代理

我将setupProxy.jshttp-proxy-middleware 一起使用,这对API 很好,但不适用于套接字

带有节点 js 的服务器代码

var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);

app.get('/', function (req, res) 
  res.sendFile(__dirname + '/index.html');
);

io.on('connection', function (socket) 
  setInterval(() => 
    console.log('emit event');
    io.emit('event',  data: 'worked successfully!' );
  , 1000);
);

http.listen(8080, function () 
  console.log('listening on *:8080');
);

带有反应的客户端代码

function App() 
  const socket = socketIOClient('/', 
    transports: ['websocket'],
  );

  useEffect(() => 
    socket.on('connect', () => 
      console.log('connected');
    );
    socket.on('event', (data) => 
      console.log(data);
    );

  , []);
  return (
    <div className='App'>
     Socket Proxy test
    </div>
  );

还有我的 setupProxy.js

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

module.exports = (app) => 
  app.use(
    '/socket.io',
    createProxyMiddleware(
      target: 'http://localhost:8080',
      changeOrigin: true,
      ws: true, // enable websocket proxy
      logLevel: 'debug',
    )
  );
;

【问题讨论】:

【参考方案1】:

我通过在服务器和客户端套接字选项中添加自定义路径解决了这个问题


  path: '/socket',

然后在代理中间件中使用该路径

  const socketProxy= createProxyMiddleware('/socket', 
    target: 'http://localhost:8080',
    changeOrigin: true,
    ws: true, 
    logLevel: 'debug',
  );

  app.use(socketProxy);

所以最终的工作代码应该是这样的:

服务器代码:

var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http, 
  path: '/socket', // added this line of code
);

app.get('/', function (req, res) 
  res.sendFile(__dirname + '/index.html');
);

io.on('connection', function (socket) 
  setInterval(() => 
    console.log('emit event');
    io.emit('event',  data: 'worked successfully!' );
  , 1000);
);

http.listen(8080, function () 
  console.log('listening on *:8080');
);

客户端代码:

function App() 
  const socket = socketIOClient('/', 
      transports: ['websocket'],
      path: '/socket', // added this line of code
  );

  useEffect(() => 
    socket.on('connect', () => 
      console.log('connected');
    );
    socket.on('event', (data) => 
      console.log(data);
    );

  , []);
  return (
    <div className='App'>
     Socket Proxy test
    </div>
  );

注意:命名空间应在&lt;URL&gt;参数中添加:const socket = socketIOClient('/namespace', ...)

最后setupProxy.js

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

module.exports = (app) => 
  const socketProxy= createProxyMiddleware('/socket', 
    target: 'http://localhost:8080',
    changeOrigin: true,
    ws: true, 
    logLevel: 'debug',
  );

  app.use(socketProxy);
;

【讨论】:

您好,我不明白这与客户端在代理后面有什么关系?如果客户端是代理背后的那个,那么客户端的通信如何到达主机?你能解释一下吗?谢谢【参考方案2】:

我通过以下步骤解决了这个问题:

    使用http protocol 创建 SocketIO 客户端。

前端:

import io from 'socket.io-client';

const socket = io(
    protocols: ["http"],
);
    setupProxy.js 中创建一个ProxyMiddleware。
module.exports = function (app) 
    app.use(
        createProxyMiddleware("/socket.io",
            target: 'http://localhost:8001',
            changeOrigin: true,
            ws: false,
        )
    );
;

注意

    socket.io-client 的默认端点是 /socket.iosocket.io-client的默认协议是ws://,这不会触发defulat的代理规则。

【讨论】:

以上是关于在 create-react-app 中使用 Socket.io-client 的 WebSockets 代理的主要内容,如果未能解决你的问题,请参考以下文章

谷歌没有在使用 create-react-app 的反应应用程序中定义

如何在 Windows 7 中使用 create-react-app

你如何在带有 Typescript 的 create-react-app 中使用 Mocha?

在 create-react-app 中,添加 Bootstrap 4?

为啥我在使用 create-react-app 的生产构建中丢失了 Bootstrap 样式?

如何在使用 create-react-app 创建的应用程序中使用带有访问令牌的 API