如何通过代理或作为中间件来操作socket.io数据?

时间:2018-12-26 21:09:35

标签: javascript node.js sockets express socket.io

为了解决这个困扰我的问题,我已经在Google和SO上搜索了两个星期。首先,我将概述我的目标是什么,然后,我将尝试解释我距离解决该目标有多近。

目标:

要在大型应用程序及其数据API之间注入小型express服务器,其唯一目的是操纵来自服务器的数据响应(或管理自定义响应来代替服务器响应的响应) )。

我们正在使用socket.io将客户端与服务器连接,实际上我实际上要修改的事件很少。我想在客户端和服务器之间来回代理的大多数事件都保持不变。

但是,有一些我想将自定义响应发送回客户端进行测试的珍贵事件

我尝试过的事情:

我已经尝试将一台基本的快速服务器同时用作socket.io-clientsocket.io服务器。我不知道如何相互代理我的请求,尤其是对于跟踪多个客户端的可能性特别警惕。链接到这里是关键,我很困惑

我也尝试过使用http-proxy,这使我非常接近,但是到目前为止,我唯一能做的就是使用内部的socket.on('data', (data) => { /* do something */ });检查有效载荷的来回情况我的proxy.on('open', socket => {});事件。

因此,尽管我可以看到大量数据来去去去,但我仍然需要机会来操纵它。

这是任何人以前做过的事情吗?有没有关于如何通过将客户端连接连接到服务器来使Express Server充当代理的好资源?

预先感谢您的专业知识。我担心这可能太先进了。

1 个答案:

答案 0 :(得分:0)

好吧,正如我所承诺的,我提出了理想解决方案的一半。理想情况下,我想来回地代理 all 事件,并且只听一些关键事件,但是我还没有弄清楚那部分内容。如果有人可以帮助我,我将永远感激不已。

相反,我只是映射了套接字两端发出的所有事件,并将它们埋在已连接的调用中。

这是我如何做我想要的事情的细节-您正常创建一个server,并在其连接上,然后从client内部启动一个.on('connection', () => {});连接呼叫。一旦处于此范围内,您就可以相对确定两个连接都是打开的,并开始来回传递事件。理想情况下,您将检查活动连接,但是如果您的服务器和/或客户端具备处理断开连接的能力,则可能还可以。

在下面的简单示例中,您将看到如何来回传递事件以及如何完成工作。就像我说的,如果有人可以通过通配符之类的方法(由于某种原因而无法工作)来帮助我,请告诉我!

// GLOBAL CONFIGS
const serverConfig = {}; // Feel free to add your desired options here

// Some of these options pertain more to me than they will to you; don't feel like
// you have to copy these configs
const clientConfig = {
  // We don't want to pre-emptivly try to connect to data-api,
  // because we need our client to give us data first.
  autoConnect: false,
  multiplex: false,
  // Disables/bypasses long polling which causes the connection to
  // be severed then re-connected (for my api at least)
  transports: ["websocket"]
};

const PORT = 3000;
const PROXY_HOST = '<api-endpoint-goes-here>'
const NAMESPACE = '<the name of your namespace, if applicable>';

// SERVER STUFF - this will connect to your client
const app = require('express')();
const server = require('http').Server(app);
const cors = require('cors');
const io = require('socket.io')(server, serverConfig);
const nsp = io.of(`/${NAMESPACE}`);

// CLIENT STUFF - this will connect to your api server as a client
const client = require('socket.io-client');
const ioClient = client(`${PROXY_HOST}/${NAMESPACE}`, clientConfig);

// Self explanatory I hope
app.use(cors());

// I am going to call this a root socket - meaning no namespace. Not entirely useful for now unless
// we want to inspect transitions in and out of our namespace, but just putting it here FYI
io.on('connection', socket => {
  console.log(`A connection to the root socket made ${socket.handshake.headers.origin}`);

  socket.on('disconnect', () => {
    console.log(`A client disconnected from the root socket.`);
  });
});

// Serve up a basic html file so that we can interact with our socket.io instance in the
// console. This index.html has a similar setup with a socket connection to both the data
// api and this test server, so I can ping events via console and test how this is working
app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname + '/index.html'));
});

// Run the server
server.listen(PORT, () => console.log('Test data server is running'));

// Here's where the real solution reveals itself for me :)

// Listen for connections to the namespace we are looking for - this is the meat & potatoes of our app
nsp.on('connection', socket => {
  console.log(`the ${NAMESPACE} namespace was connected`);

  // Time to initiate a connection to the ioClient because we need it for the app now
  ioClient.connect();

  // Now check to make sure ioCLient is connected. Once we get inside here, we can be 
  // reasonably sure that we have a connection to both the client, and the data-api
  ioClient.on('connect', () => {
    // Acknowledge we have connected to the data-api
    console.log('Connected to data-api via socket.io');

    // Events sent from data-api
    ioClient.on('<your event>', data => {
      socket.emit('<your event>', data);
    });

    ioClient.on('<your event with two params>', (data1, data2) => {
      socket.emit('<your event with two params>', data1, data2);
    });
    
    // ... etc

    // Other event catchers for ioClient
    ioClient.on('disconnect', () => {
      console.log('Disconnected from the data-api');
    });
    
    ioClient.on('error', err => {
      console.error('Error with the data-api connection: ', err);
    });

    // Events sent from the app client
    socket.on('<your event>', data => {
      ioClient.emit('<your event>', data);
    });

    socket.on('<your event with two params>', (data1, data2) => {
      ioClient.emit('<your event with two params>', data1, data2);
    });
    
    // ... etc
  });
});