SOCKET.IO使用http-proxy-middleware代理

1,514 阅读2分钟

问题还是要接回上次的socket.io上,之前socket.io直接写死了了url,所以在到处去部署网站的时候可能要改掉写死的地址重新build比较耗时,由于工程中原本已经用了http-proxy-middleware的代理,所以就想要统一都用这个代理,不把url写死了。

socket.io的服务方式

根据socket.io的官方文档,有两种方式可以获得到socket对象,一种是直接由io方法得到,一种是根据manager方法得到

//io方法
import io from 'socket.io-client'
const SOCKET=io('http://localhost:8088/namespace')

io方法获取socket对象的时候,URI必须给定,而且固定将"/"后面的内容认作namespace。此处的URI如果不给定,或者只给了“/”后的内容,则会默认地址为窗口ip及端口号。

//部分源码如下

interface SocketIOClientStatic {

    /**
     * Looks up an existing 'Manager' for multiplexing. If the user summons:
     *     'io( 'http://localhost/a' );'
     *     'io( 'http://localhost/b' );'
     *
     * We reuse the existing instance based on the same scheme/port/host, and
     * we initialize sockets for each namespace. If autoConnect isn't set to
     * false in the options, then we'll automatically connect
     * @param uri The uri that we'll connect to, including the namespace, where '/' is the default one (e.g. http://localhost:4000/somenamespace)
     * @opts Any connect options that we want to pass along
     * @return A Socket object
     */
    ( uri: string, opts?: SocketIOClient.ConnectOpts ): SocketIOClient.Socket;

manager方法获取socket对象的时候,此处的URI也必须给定,但并不固定"/"后面的内容认作namespace,这就给代理或者多个namespace带来操作可能。

//manager方法

const { Manager } = require("socket.io-client");
const manager = new Manager("http://localhost:8088");
const SOCKET = manager.socket("/namespace");

http-proxy-middleware的代理设置

http-proxy-middleware是本质是转发时重写http://localhost:port/api的内容为目标内容(`target`),所以只要保证我们的请求URL能够保留这个格式就可以了。

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

module.exports = function (app) {
  app.use(
    createProxyMiddleware("/api", {
      target: 'http://localhost:9887/',
      pathRewrite: {
        "^/api": "",
      },
      changeOrigin: true,
      secure: false, // 是否验证证书
      ws: true, // 启用websocket
    })
  );
};

socket.io使用代理

根据之前所说的http-proxy-middleware的内容,我们只需要保证URL有ip:port/api即可,如下:

const { Manager } = require("socket.io-client");

const manager = new Manager("", {
  reconnectionDelayMax: 10000,
  path: "/api/socket.io",
});

const SOCKETIO = manager.socket("/namespace");

这里/apihttp-proxy-middleware设置的,path参数可以保证浏览器发出socket.io请求的时候,设置的地址端口后面可以添加我们想要的路径。最后得到socket对象时需要给予之前确定好的命名空间,这样就可以顺利连接上了。此时我们的申请URL如下:

Request URL: 
http://192.168.6.141:8088/api/socket.io/EIO=3&transport=polling&t=NWMqLrc&sid=88ea80c6276f41ef90cf10fec49e5c08

//这里前面是的请求URL内容为  协议://ip地址:端口/api/socket.io/巴拉巴拉

其实这里的逻辑就是:

  1. manager可以设置我们想要的ip与端口,并且可以给定后续添加的路径,保证可以正常连接
  2. 用manager的方法设置命名空间,保证可以正常通信