Electron使用时拦截HTTP请求的解决方案
程序员文章站
2022-07-11 17:01:46
背景 最近在做一个Web和Electron共用一份代码的工程,由于使用到了第三方的库(我们是在线地图),该库的认证方式是请求时加key,并且它在后台会校验referer。 于是问题就来了,Electron是运行在本地的,http请求的时候,是不会带有授权Web站点的referer的。导致认证失败,无 ......
背景
最近在做一个web和electron共用一份代码的工程,由于使用到了第三方的库(我们是在线地图),该库的认证方式是请求时加key,并且它在后台会校验referer。
于是问题就来了,electron是运行在本地的,http请求的时候,是不会带有授权web站点的referer的。导致认证失败,无法调用所需的api接口。
分析
既然http请求发送的时候不带referer,那么我们给他加上去,是不是就可以了呢?
对策
方法1:自定义http协议,在发送请求时,补上referer
// 注册自定义协议 protocol.registerstandardschemes(['app', '自定义协议'], { secure: true }) // 自定义协议的具体实现 protocol.registerhttpprotocol('自定义协议', (req, cb) => { cb({ url: “特定的url地址”, referrer: "http://被授权的referrer头信息" }) }) // 发送请求时可以使用 自定义协议://url地址 的形式来发送请求
发送请求时可以使用 自定义协议://url地址 的形式来发送请求。当然,我们这个例子里面只是追加了referrer,其实根据实际需求还可以做很多其它事情。
相关api文档:https://electronjs.org/docs/api/protocol#protocolregisterhttpprotocolscheme-handler-completion
方法2:修改窗口会话中发送请求前的行为
本来以为方法1以及很完美的解决了问题,但是,在自定义协议认证成功后,在api的使用过程中,api内部主动发送了http请求,这时的api请求没有使用自定义协议,再次认证失败了。于是我想到有个办法,很天真的认为可以解决问题。失败的做法如下:
protocol.intercepthttpprotocol("http", (req, cb) => { // 此处可以追加url是否匹配的逻辑判断 cb({ url:req.url, referrer: "http://授权的referrer头信息" }) })
相关api文档:https://electronjs.org/docs/api/protocol#protocolintercepthttpprotocolscheme-handler-completion
我直接拦截了原生的http协议,追加referrer信息,发生的结果是,http->截获http->修改后发送http->截获http->修改后发送http->......发生了无限循环!!!
于是只能另辟蹊径,寻找其余解决方案。发现了webquest的行为可以捕获。于是在onbeforesendheaders的时机,追加referer信息。正确的做法如下:
// 需要拦截的url地址 const xxx_filter = { urls: ["https://*.xxx.com/*", "http://*.yyy.com/*"] } session.defaultsession.webrequest.onbeforesendheaders(xxx_filter, (details, callback) => { details.requestheaders['referer'] = 'http://授权的referer头信息' callback({ requestheaders: details.requestheaders }); })
相关api文档:https://electronjs.org/docs/api/web-request
总结
通过对webrequest的捕获,解决了本次的问题,并且把自定义协议那个案也可以替换掉。webrequest还有好几个阶段的行为可以自定义,可以适用于不同场景的需求。