跨端实现之网络库拦截

工作中有些一些场景要拦截或改写网络库,比如在做跨端基建的时候,移动端同学说:原生拦截不好使,我和你约定一个request 方法吧。你直接用这个 request 方法调用。在你质疑他技术水平 :)的同时,我们可以思考一下这个场景。如果 H5 侧要拦截所有网络请求并用 request,大家怎么做。

业务同学使用的第三方网络库都不一样,axios,fetch,fly,一大堆。但大家观察一下 chrome 的请求类型基础就两个 fetch 和 XHR。那么搞定这两个我们的这个问题就解决了。

基本结构很简单,你让 llm 帮你写即可,我们仅聊聊思路和跨端场景下的边界场景。首先是劫持或是替换 fetch 和 XHR,以 fetch 举例。

js 复制代码
// ez code
const originalFetch = globalThis.fetch
const originalXMLHttpRequest = globalThis.XMLHttpRequest

globalThis.fetch = myFetch 
globalThis.XMLHttpRequest = myXMLHttpRequest

// my fetch

const myFetch = async function (
    input: RequestInfo | URL,
    options: RequestInit = {},
  ): Promise<Response> {
    try {
      // 处理请求参数
      const url = input.toString()
      const method = options?.method || 'GET'
      const headers = {}
      const body = xxx
  

      // customRequest 是移动端给的一个网络请求han'shu
      const response = await customRequest({
        body: JSON.stringify(body),
        url,
        method,
        headers,
        timeout: 10000,
      });

      try {
        response.data = JSON.parse(response.responseText);
      } catch {
        console.error(
          "Failed to parse response as JSON, using raw response text."
        );
        response.data = {};
      }
      const out = {
        ok: response.statusCode >= 200 && response.statusCode < 300,
        status: response.statusCode,
        statusText: `${response.statusCode}` || "",
        headers: new Headers(response.headers || {}),
        json: () => {
          return Promise.resolve(response.data);
        },
        text: () => Promise.resolve(response.responseText || ""),
        blob: () => Promise.reject(new Error("Blob not supported in fly")),
        formData: () =>
          Promise.reject(new Error("FormData not supported in fly")),
        arrayBuffer: () => Promise.resolve(response.data),
        clone: () => ({
          ok: response.statusCode >= 200 && response.statusCode < 300,
          status: response.statusCode,
          statusText: `${response.statusCode}` || "",
          headers: new Headers(response.headers || {}),
          json: () => Promise.resolve(response.data),
          text: () => Promise.resolve(response.responseText || ""),
          blob: () => Promise.reject(new Error("Blob not supported in fly")),
          formData: () =>
            Promise.reject(new Error("FormData not supported in fly")),
          arrayBuffer: () => Promise.resolve(response.data),
        }),
        data: {
          ...response.data,
          json: () => {
            return Promise.resolve(response.data);
          },
        },
        body: new ReadableStream({
          start(controller) {
            // 将响应数据推送到流中
            const data = response.data || response.responseText || "";
            const encoder = new TextEncoder();
            controller.enqueue(
              encoder.encode(
                typeof data === "string" ? data : JSON.stringify(data)
              )
            );
            controller.close();
          },
        }),
        redirected: false,
        type: "",
        bytes: null,
        bodyUsed: false,
        url,
      } as Response;
      return out
    } catch (error) {
      // 创建一个错误响应
    }
}

这一块需要注意 fetch 请求的 body 需要一个 ReadStream 类型。大多数第三方库会使用这个值。如果没有这个值,即使你请求正常也会拿到空对象(如果第三方库的默认是空)。

常见问题

这一块你基本上可以用 vibe coding。但是代码结构非常重要,因为会有一些边界场景,比如 override 代码(运行时代码执行比业务代码慢导致部分网络请求用原生 fetch / XHR)。有几个思路,

方案一:阻塞业务代码

阻塞主流程直到网络库覆盖完成。优点是直截了当,非常粗暴。但问题是

  1. 运行时代码侵入到业务代码里了
  2. 移动端提供的 request 方法可能不可用,因为 H5 和移动端往往通过 bridge 桥接。桥接流程如果存在同步操作。可能移动端在第一时间无法正常承接你的网络请求,但请求已经进去了。

方案二:网络库重发

相对和业务代码解耦,但问题是

  1. 业务代码注定要面临前几次网络请求被重发的问题。如果处理不好,用户可能会看到接口报错

方案三:容器侧注入运行时

相对常用的运行时注入方案,先对逻辑容器注入,运行时对象。

对于 iOS

swift 复制代码
jsContext.executeJavaScript(`globalfetch = xxx`)

等移动端确定后再加载 H5 的代码,建立业务实例。这样可以完全解耦。

相关推荐
ObjectX前端实验室32 分钟前
React Fiber 双缓冲树机制深度解析
前端·react.js
高斯林.神犇1 小时前
javaWeb基础
前端·chrome
用户21411832636021 小时前
dify案例分享-Qwen3-VL+Dify:从作业 OCR 到视频字幕,多模态识别工作流一步教,附体验链接
前端
南屿im2 小时前
把代码变成“可改的树”:一文读懂前端 AST 的原理与实战
前端·javascript
charlie1145141912 小时前
从《Life of A Pixel》来看Chrome的渲染机制
前端·chrome·学习·渲染·浏览器·原理分析
HWL56792 小时前
输入框内容粘贴时 &nbsp; 字符净化问题
前端·vue.js·后端·node.js
梦6502 小时前
JQ 的 AJAX 请求方法
前端·ajax
ObjectX前端实验室2 小时前
【react18原理探究实践】分层解析React Fiber 核心工作流程
前端·react.js
IT_陈寒2 小时前
「JavaScript 性能优化:10个让V8引擎疯狂提速的编码技巧」
前端·人工智能·后端
ObjectX前端实验室3 小时前
【react18原理探究实践】scheduler原理之Task 完整生命周期解析
前端·react.js