首页 > 解决方案 > JavaScript WebSocket 类

问题描述

我需要记录 WebSocket 流量,所以我要编写一个 Chrome 扩展程序,它会注入一些应该起到作用的 JavaScript 代码。

WebSocket = new Proxy(WebSocket, {
  construct: (target, args) => {
    console.log('new WebSocket instance');
    return new target(...args);
  }
})

我需要覆盖什么方法来记录发送和接收的消息?

如何修改发送/接收的此类消息?一个简单的工作代码将不胜感激。

标签: javascriptgoogle-chrome-extension

解决方案


而不是代理,我将构造并返回一个普通的 WebSocket,并根据需要附加您自己的自定义方法:

const origWebSocket = window.WebSocket;
window.WebSocket = function(url) {
  const socket = new origWebSocket(url);
  socket.send = (msg) => {
    console.log('intercepted send:', msg);
    origWebSocket.prototype.send.call(socket, msg);
  };
  socket.addEventListener('message', (event) => {
    console.log('intercepted receive:', event.data);
  });
  return socket;
};

// patching done
const socket = new WebSocket('wss://echo.websocket.org');
socket.onopen = () => {
  socket.send('hi');
};

要同时修改传入消息,您可以修补onmessage实例的addEventListener属性(如果需要,还可以修补属性),以便在收到消息时,在用户的回调运行之前首先通过您的自定义函数:

const origWebSocket = window.WebSocket;
const origOnMessage = Object.getOwnPropertyDescriptor(WebSocket.prototype, 'onmessage').set;
window.WebSocket = function(url) {
  const socket = new origWebSocket(url);
  Object.defineProperty(socket, 'onmessage', {
    set(cb) {
      origOnMessage.call(socket, (e) => {
        // Have to use defineProperty because `data` is a getter on the prototype
        Object.defineProperty(e, 'data', { value: e.data + ' modified' });
        cb(e);
      });
    }
  });
  socket.send = (msg) => {
    console.log('intercepted send:', msg);
    origWebSocket.prototype.send.call(socket, msg);
  };
  socket.addEventListener('message', (event) => {
    console.log('intercepted receive:', event.data);
    event.data = 'foobar';
  });
  return socket;
};

// patching done
const socket = new WebSocket('wss://echo.websocket.org');
socket.onopen = () => {
  socket.send('hi');
};
socket.onmessage = e => console.log('consumer sees message:', e.data);


推荐阅读