拦截HTTP的多种方式

部分场景下需要修改请求报文信息,可以利用 AOP 思维(切面编程),对请求进行拦截处理。Web 中有见的几种发送请求的方式:

  • XMLHttpRequest
  • fetch
  • window.navigator.sendBeacon
  • new Image
  • service worker

针对这几种不同的场景,分别拦截处理它的 URL 和请求参数

(一)设计

符合条件 使用新的 URL , BDOY 不符合条件 请求 Filter Adaptor 发送请求

FilterAdaptor 成对出现,满足过滤过滤器的条件后,使用对用的适配器修改 URLBDOY

(二)不同的请求方式

1. XMLHttpRequest

XHR 的核心思路:

  1. 拦截 open,缓存参数信息
  2. 拦截 send,对 urlbody处理
  3. 调用原生 open、send 发送请求

核心代码实现:

ts 复制代码
class CustomXhr extends NativeXhr {
  private _method!: string;
  private _src = "" as K;
  private _async!: boolean;
  private _username?: string | null;
  private _password?: string | null;
  private _headers: Record<string, string> = {};

  open(
    method: string,
    url: K,
    async: boolean = true,
    username?: string | null,
    password?: string | null
  ) {
    this._method = method;
    this._src = url;
    this._async = async;
    this._username = username;
    this._password = password;
  }

  setRequestHeader(name: string, value: string) {
    this._headers[name] = value;
  }

  send(body?: T) {
    let url = "" as K;
    let data = body;

    if (!_this.useNative) {
      [url, data] = _this.callFilterAndAdapter(this._src, body);
    }

    // Open
    super.open(this._method, url, this._async, this._username, this._password);

    // 设置请请求头
    Object.keys(this._headers).forEach((key) => {
      super.setRequestHeader(key, this._headers[key]);
    });

    return super.send(data);
  }
}

2. fetch

fetch 拦截的思路:

  1. 使用函数对原生 fetch 进行包装

核心代码实现:

ts 复制代码
const NativeFetch = window.fetch;

function CustomFetch(input: K, init?: RequestInit) {
  if (_this.useNative) {
    return NativeFetch(input, init);
  }

  const [url, data] = _this.callFilterAndAdapter(input, init?.body as T);
  if (init && data) {
    init.body = data;
  }
  return NativeFetch(url, init);
}

window.fetch = CustomFetch as typeof window.fetch;

3. window.navigator.sendBeacon

sendBeacon 的拦截思路:

  1. 同 fetch 的实现思路,对原生的 window.navigator.sendBeacon 进行包装一层

核心代码:

ts 复制代码
const oldSendBeacon = window.navigator.sendBeacon;
window.navigator.sendBeacon = (url: K, data: T) => {
  // 使用原生方式
  if (this.useNative) {
    return oldSendBeacon.call(window.navigator, url, data);
  }

  const [newUrl, newData] = this.callFilterAndAdapter(url, data);
  return oldSendBeacon.call(window.navigator, newUrl, newData);
};

备注:sendBeacon 的上下文一定要是window.navigator,所以需要使用oldSendBeacon.call(window.navigator, url, data)

4. new Image

new Image的拦截思路:

  1. CustomImage 类继承自 Window.Image
  2. 使用 set、get 拦截 src属性的读写

核心代码实现:

ts 复制代码
const NativeImage = window.Image;

class CustomImage extends NativeImage {
  private _src!: K;

  set src(value: K) {
    if (_this.useNative) {
      this._src = value;
      return;
    }

    this._src = _this.newSetHandler(value);
    this.setAttribute("src", this._src);
  }

  get src() {
    return this._src;
  }
}

window.Image = CustomImage;

5. service worker

这个就不细聊了,有兴趣的可以自己去看下

(三)源码

install

bash 复制代码
npm i @swl/http-interceptor

源代码: https://github.com/swlws/http-interceptor

相关推荐
宇砾23 分钟前
HTTPS的工作流程
网络协议·http·https
JaydenAI25 分钟前
[MAF预定义Agent中间件-03]FunctionInvocationDelegatingAgent:将AOP引入函数调用
ai·c#·agent·aop·maf
sinat_2554878113 小时前
第七部分。介绍MVC(模型-视图-控制器)模式
java·ide·http·tomcat·intellij-idea
齐鲁大虾19 小时前
如何彻底解决从公网HTTP页面请求私有HTTP资源跨域问题
网络·网络协议·http
韩曙亮20 小时前
【Flutter】Flutter 中的 Android / iOS 特殊配置 ① ( 网络权限配置 | HTTP 明文传输配置 | 应用名称配置 )
android·网络·flutter·http·ios·网络权限
WIZnet1 天前
W55RP20-EVB-MKR 模块 MicroPython 实战 (11):HTTP 协议与 OneNET 平台数据上云
网络·网络协议·http
许彰午1 天前
微服务安全上下文的透明传递——ThreadLocal透传与HTTP头转发的完整链路
安全·http·微服务
触底反弹1 天前
从 Bun 到 DeepSeek:用 TypeScript 构建你的第一个 AI Agent
人工智能·http·typescript
遇事不決洛必達1 天前
【爬虫随笔】深入理解 HTTP/HTTPS 协议、接口交互与会话机制
爬虫·网络协议·http·https·session
华山令狐虫1 天前
DBAPI 接入 Milvus 向量数据库:HTTP 执行器参数映射实战
数据库·http·milvus·dbapi