Electron中拦截并响应WSS请求的等效实现方法
Electron WSS请求无侵入拦截实现方案
问题背景
以下代码可实现Electron中HTTPS请求的拦截与响应:
mainWindow.webContents.session.protocol.interceptBufferProtocol( 'https', async ( { url, method, uploadData: [{ bytes: requestPayload } = {}] = [], headers: requestHeaders }, callback ) => { const { statusCode, headers: responseHeaders, payload: responsePayload } = await doSomething({ url, headers: requestHeaders, method, payload: requestPayload }); callback({ statusCode, headers: responseHeaders, data: responsePayload }); } );
该实现方案无需启动本地服务,也无需替换渲染进程侧的fetch、XMLHttpRequest等全局变量。需求是对WSS请求实现同等的拦截与响应效果。
实现方式
Electron没有提供和HTTPS拦截完全同名的WSS拦截API,因为WSS基于WebSocket长连接双工协议,和HTTP单次请求-响应的模型存在差异,但可以通过协议层注册流拦截器的方式实现完全同等的无侵入效果,不需要修改渲染进程全局对象、不需要启动本地代理服务。
- 正式拦截前需要先给wss协议配置对应权限,代码要放在app模块的
ready事件之前执行:
const { protocol } = require('electron'); protocol.registerSchemesAsPrivileged([ { scheme: 'wss', privileges: { standard: true, secure: true, stream: true, bypassCSP: true } } ]);
- 22版本以下的Electron使用
registerStreamProtocol拦截wss协议,核心逻辑和HTTPS拦截对齐,只是把单次返回的Buffer替换成双工流承载长连接的双向数据:
const crypto = require('crypto'); const { Duplex } = require('stream'); // WebSocket握手固定逻辑:计算Sec-WebSocket-Accept校验值 const getWsAccept = (key) => { return crypto .createHash('sha1') .update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11') .digest('base64'); }; mainWindow.webContents.session.protocol.registerStreamProtocol( 'wss', async (request, callback) => { const { url, headers } = request; // 自定义双工流,处理双向收发的WebSocket数据 const wsStream = new Duplex({ read() {}, async write(chunk, _, next) { // chunk为渲染进程发送的WebSocket帧二进制数据 const { responseFrame } = await doSomething({ url, headers, requestFrame: chunk }); // 把自定义处理后的响应帧推回流,渲染进程即可收到对应消息 this.push(responseFrame); next(); } }); // 返回WebSocket握手响应,挂载自定义流承载后续通信 callback({ statusCode: 101, // WebSocket协议切换固定状态码 headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade', 'Sec-WebSocket-Accept': getWsAccept(headers['sec-websocket-key']) }, data: wsStream }); } );
- Electron 22及以上版本可以直接使用标准的
protocol.handleAPI实现,逻辑更简洁,不需要引入Node.js流模块,直接返回标准Web API的Response对象即可:
mainWindow.webContents.session.protocol.handle('wss', async (request) => { const { url, headers } = request; // 自定义双工可读可写流,对接业务处理逻辑 const stream = new ReadableStream({ start(controller) { // 此处监听请求上传的帧数据,处理后通过controller.enqueue返回响应即可 } }); // 返回握手响应和通信流 return new Response(stream, { status: 101, headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade', 'Sec-WebSocket-Accept': getWsAccept(headers.get('sec-websocket-key')) } }); });
内容的提问来源于stack exchange,提问作者KaKi87
相关产品推荐
相关产品推荐

