详解electron如何拦截网络请求并处理响应

 更新时间:2023年12月07日 16:56:41   作者:小气小憩  
这篇文章主要为大家详细介绍了electron如何拦截网络请求并处理响应,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下

需求背景

electron中的web应用离线方案,由于目前的web应用已经大量接入了,想要各个产线去对离线方案进行大量配置更改,成本过高。所以期望离线方案能对现有web应用进行无侵入接入。

实现方案

electron版本:12.1.1

方案一 onBeforeRequest + 自定义协议

使用webRequest.onBeforeRequest拦截所有请求,通过判断逻辑指定处理某些url。

这些特定的url,需要通过自定义协议处理。

注册私有协议

const ses = session.fromPartition('persist:my-partition');
ses.protocol.registerFileProtocol('toLocal', (request, callback) => {
  //这只是个举例,实际需要通过request.url判断使用哪个本地文件
  callback({
    path: '/Users/xxx/Documents/project/electron-react/dist/xxx.html',
    statusCode: 200,
    charset: 'utf-8',
    mimeType: 'text/html',
  });

对特定url进行识别,转发到私有协议中

ses.webRequest.onBeforeRequest({ urls: ['*://*/*'] }, (details: any, callback: any) => {
  // 检查请求URL是否为特定资源
  if (details.url === 'https://xx.xx.com/') {
    callback({
      redirectURL: 'toLocal://xx.xx.com',
    });
  } else {
    // 允许其他请求正常进行
    callback({});
  }
});

自定义协议在拦截html时,需要开启访问session(localstorage,cookie等)的权限

protocol.registerSchemesAsPrivileged([
  {
    scheme: 'toLocal',
    privileges: {
      standard: true,
      secure: true,
      supportFetchAPI: true,
      bypassCSP: true,
      corsEnabled: true,
    },
  },
]);

问题

使用onBeforeRequest+redirectURL转发的url,会直接改变web中的request url

私有协议无法使用cookie

在部分验证url的场景,会出现无权限/跨域问题

方案二 只使用拦截器

拦截自定义协议toLocalhttps协议的请求,在https协议中处理指定url。命中后转发到toLocal协议中,进行本地文件的读取。未命中则转发请求。

ses.protocol.interceptFileProtocol('toLocal', (request, callback) => {
    callback({
      path: '/Users/xxx/Documents/project/electron-react/dist/xxx.html',
    });
  });
ses.protocol.interceptHttpProtocol('https', (request, callback) => {
    if (request.url === 'https://xxx.xx.com/') {
      callback({
        url: 'toLocal://xxx.xx.com',
        method: request.method,
      });
    } else {
      const uploadData = request.uploadData && {
        contentType: 'application/json',
        data: request.uploadData.map((i) => i.bytes.toString()).join(''),
      };
      callback({
        url: request.url,
        method: request.method,
        session: session.defaultSession,
        uploadData,
      });
    }
  });

问题

拦截器只能注册一种,已先注册的为主。后续注册相同的scheme都会失败。

由于以上问题,拦截请求时,考虑使用interceptHttpProtocol

不代理的请求需要转发问题,request中的uploadData数据格式和response中的uploadData数据格式不一致。

当前代码中,处理post请求中,携带file时无法处理。目前正在解决中...

interceptHttpProtocol中的request和callback定义

// request定义
interface ProtocolRequest {
    // Docs: https://electronjs.org/docs/api/structures/protocol-request
    headers: Record<string, string>;
    method: string;
    referrer: string;
    uploadData?: UploadData[];
    url: string;
  }
  
  interface UploadData {

    // Docs: https://electronjs.org/docs/api/structures/upload-data

    /**
     * UUID of blob data. Use ses.getBlobData method to retrieve the data.
     */
    blobUUID?: string;
    /**
     * Content being sent.
     */
    bytes: Buffer;
    /**
     * Path of file being uploaded.
     */
    file?: string;
  }
//  callback传参定义
 interface ProtocolResponse {

    // Docs: https://electronjs.org/docs/api/structures/protocol-response

    /**
     * The charset of response body, default is `"utf-8"`.
     */
    charset?: string;
    /**
     * The response body. When returning stream as response, this is a Node.js readable
     * stream representing the response body. When returning `Buffer` as response, this
     * is a `Buffer`. When returning `String` as response, this is a `String`. This is
     * ignored for other types of responses.
     */
    data?: (Buffer) | (string) | (NodeJS.ReadableStream);
    /**
     * When assigned, the `request` will fail with the `error` number . For the
     * available error numbers you can use, please see the net error list.
     */
    error?: number;
    /**
     * An object containing the response headers. The keys must be String, and values
     * must be either String or Array of String.
     */
    headers?: Record<string, (string) | (string[])>;
    /**
     * The HTTP `method`. This is only used for file and URL responses.
     */
    method?: string;
    /**
     * The MIME type of response body, default is `"text/html"`. Setting `mimeType`
     * would implicitly set the `content-type` header in response, but if
     * `content-type` is already set in `headers`, the `mimeType` would be ignored.
     */
    mimeType?: string;
    /**
     * Path to the file which would be sent as response body. This is only used for
     * file responses.
     */
    path?: string;
    /**
     * The `referrer` URL. This is only used for file and URL responses.
     */
    referrer?: string;
    /**
     * The session used for requesting URL, by default the HTTP request will reuse the
     * current session. Setting `session` to `null` would use a random independent
     * session. This is only used for URL responses.
     */
    session?: Session;
    /**
     * The HTTP response code, default is 200.
     */
    statusCode?: number;
    /**
     * The data used as upload data. This is only used for URL responses when `method`
     * is `"POST"`.
     */
    uploadData?: ProtocolResponseUploadData;
    /**
     * Download the `url` and pipe the result as response body. This is only used for
     * URL responses.
     */
    url?: string;
  }
  
 interface ProtocolResponseUploadData {
    // Docs: https://electronjs.org/docs/api/structures/protocol-response-upload-data
    /**
     * MIME type of the content.
     */
    contentType: string;
    /**
     * Content to be sent.
     */
    data: (string) | (Buffer);
  }

方案三:代理

安全过不去 弃

由于安全过不去,基本没做调研,只知道有个setProxy

ses.setProxy()

总结

以上方案目前都不太满足,调研了近3天,依旧没有一个很好的解决方案。

在开始调研前的方案

我是真没想到!我查了这么久,愣是没找到能对webContent的网络请求完全拦截的api!!!

方案一是目前最理想的方案了,开发成本极低。但是拦截html会出现问题,redirectURL导致web中的请求地址更改解决不了!

到此这篇关于详解electron如何拦截网络请求并处理响应的文章就介绍到这了,更多相关electron拦截网络请求内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 手把手教你如何使用nodejs编写cli命令行

    手把手教你如何使用nodejs编写cli命令行

    这篇文章主要介绍了手把手教你如何使用nodejs编写cli命令行,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • nvm管理node无法正常切换node版本问题的解决方法

    nvm管理node无法正常切换node版本问题的解决方法

    相信一定会有存在一些小伙伴 明明都已经按着操作卸载node 和安装nvm 了但是 依旧无法正常通过nvm管理node,本文将给大家介绍nvm管理node无法正常切换node版本问题的解决方法,需要的朋友可以参考下
    2024-01-01
  • nodejs搭建本地服务器轻松解决跨域问题

    nodejs搭建本地服务器轻松解决跨域问题

    这篇文章主要介绍了利用nodejs搭建本地服务器 解决跨域问题,需要的朋友可以参考下
    2018-03-03
  • 简单模拟node.js中require的加载机制

    简单模拟node.js中require的加载机制

    大家都知道Node 采用的模块化结构是按照 CommonJS 规范,模块与文件是一一对应关系,即加载一个模块,实际上就是加载对应的一个模块文件。这篇文章显示简单的介绍了nodejs中require的加载机制,而后简单的模拟require函数,有需要的朋友们下面来一起看看吧。
    2016-10-10
  • node.js中对Event Loop事件循环的理解与应用实例分析

    node.js中对Event Loop事件循环的理解与应用实例分析

    这篇文章主要介绍了node.js中对Event Loop事件循环的理解与应用,结合实例形式分析了node.js中Event Loop事件循环相关原理、使用方法及操作注意事项,需要的朋友可以参考下
    2020-02-02
  • ubuntu编译nodejs所需的软件并安装

    ubuntu编译nodejs所需的软件并安装

    Node 在 Linux,Macintosh,Solaris 这几个系统上都可以完美的运行,linux 的发行版本当中使用 Ubuntu 相当适合。这也是我们为什么要尝试在 ubuntu 上安装 Node.js,
    2017-09-09
  • 浅谈Express.js解析Post数据类型的正确姿势

    浅谈Express.js解析Post数据类型的正确姿势

    这篇文章主要介绍了Express.js解析Post数据类型的正确姿势,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • node链接mongodb数据库的方法详解【阿里云服务器环境ubuntu】

    node链接mongodb数据库的方法详解【阿里云服务器环境ubuntu】

    这篇文章主要介绍了node链接mongodb数据库的方法,结合实例形式分析了nodejs基于阿里云服务器环境ubuntu下实现连接MongoDB数据库的相关操作技巧,需要的朋友可以参考下
    2019-03-03
  • NodeJS创建最简单的HTTP服务器

    NodeJS创建最简单的HTTP服务器

    这篇文章主要介绍了NodeJS创建最简单的HTTP服务器的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • 使用nodejs实现JSON文件自动转Excel的工具(推荐)

    使用nodejs实现JSON文件自动转Excel的工具(推荐)

    这篇文章主要介绍了使用nodejs实现,JSON文件自动转Excel的工具,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06

最新评论