Electron中interceptBufferProtocol弃用后,如何用protocol.handle拦截HTTP/HTTPS?
问题
我在Electron应用里要做一个验证码收集弹窗,找了个旧仓库的代码,原代码用的是旧版Electron的interceptBufferProtocol,现在新版Electron要用protocol.handle替换,但我改完后没法实现HTTP协议拦截。下面是原函数和我改写后的函数,求正确的更新方式。
原函数
function SetupIntercept() { protocol.interceptBufferProtocol('http', (req, callback) => { if(req.url == 'https://www.google.com/recaptcha/api2/demo') { fs.readFile(__dirname + '/captcha.html', 'utf8', function(err, html){ callback({mimeType: 'text/html', data: Buffer.from(html)}); }); }else{ const request = net.request(req) request.on('response', res => { const chunks = [] res.on('data', chunk => { chunks.push(Buffer.from(chunk)) }) res.on('end', async () => { const file = Buffer.concat(chunks) callback(file) }) }) if (req.uploadData) { req.uploadData.forEach(part => { if (part.bytes) { request.write(part.bytes) } else if (part.file) { request.write(readFileSync(part.file)) } }) } request.end() } }) };
改写后的函数
function SetupIntercept() { protocol.handle('http', async (req) => { if (req.url === 'http://supremenewyork.com/') { try { const html = await fs.promises.readFile(__dirname + '/captcha.html', 'utf8'); return { mimeType: 'text/html', data: Buffer.from(html), }; } catch (err) { console.error('Error reading captcha.html:', err); return { mimeType: 'text/plain', data: Buffer.from('Error loading page'), }; } } else { return new Promise((resolve, reject) => { const request = net.request(req); request.on('response', (res) => { const chunks = []; res.on('data', (chunk) => { chunks.push(Buffer.from(chunk)); }); res.on('end', () => { const file = Buffer.concat(chunks); resolve({ data: file }); }); res.on('error', (error) => { console.error('Error in response:', error); reject({ mimeType: 'text/plain', data: Buffer.from('Error loading page'), }); }); }); if (req.uploadData) { req.uploadData.forEach((part) => { if (part.bytes) { request.write(part.bytes); } else if (part.file) { request.write(readFileSync(part.file)); } }); } request.end(); }); } }); }
解决方案
你的改写存在几个关键问题,导致拦截失效,修复要点如下:
1. 同时处理HTTP和HTTPS协议
原代码判断的是HTTPS开头的URL,但只注册了HTTP协议的处理器。新版Electron中protocol.handle需要分别为http和https注册处理器,否则HTTPS请求不会被拦截。
2. 转发请求时保留完整响应信息
原代码仅返回拼接的Buffer,新版需要传递原始响应的状态码、响应头等信息,否则页面可能无法正常渲染。
3. 完善错误处理逻辑
给net.request添加错误监听,避免请求失败时出现未处理的Promise拒绝。
修复后的完整代码
const { protocol, net } = require('electron'); const fs = require('fs').promises; const { readFileSync } = require('fs'); function SetupIntercept() { // 同时注册HTTP和HTTPS协议处理器 ['http', 'https'].forEach(scheme => { protocol.handle(scheme, async (req) => { // 替换为你需要拦截的目标URL const targetUrl = 'https://www.google.com/recaptcha/api2/demo'; if (req.url === targetUrl) { try { const html = await fs.readFile(`${__dirname}/captcha.html`, 'utf8'); return new Response(html, { headers: { 'Content-Type': 'text/html' } }); } catch (err) { console.error('读取captcha.html失败:', err); return new Response('加载页面失败', { status: 500, headers: { 'Content-Type': 'text/plain' } }); } } else { return new Promise((resolve, reject) => { const request = net.request(req); // 监听请求错误 request.on('error', (error) => { console.error('请求出错:', error); reject(new Response('请求失败', { status: 500, headers: { 'Content-Type': 'text/plain' } })); }); request.on('response', (res) => { const chunks = []; res.on('data', (chunk) => chunks.push(chunk)); res.on('end', () => { const data = Buffer.concat(chunks); // 构建Response,保留原始状态码和响应头 const response = new Response(data, { status: res.statusCode, headers: res.headers }); resolve(response); }); res.on('error', (error) => { console.error('响应出错:', error); reject(new Response('加载页面失败', { status: 500, headers: { 'Content-Type': 'text/plain' } })); }); }); if (req.uploadData) { req.uploadData.forEach((part) => { if (part.bytes) { request.write(part.bytes); } else if (part.file) { request.write(readFileSync(part.file)); } }); } request.end(); }); } }); }); }
额外注意事项
- 必须在
app.whenReady()之后调用SetupIntercept(),Electron的协议API需要在应用就绪后才能使用。 - 如果目标URL存在重定向或带查询参数,需要调整
req.url的匹配逻辑(比如忽略查询参数、统一路径大小写)。 - 新版Electron推荐使用
Response对象返回拦截结果,比直接返回普通对象更规范,也更兼容浏览器端的处理逻辑。
内容的提问来源于stack exchange,提问作者JediSZN
相关产品推荐
相关产品推荐

