拦截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

相关推荐
丿罗小黑4 小时前
Pytest项目_day01(HTTP接口)
网络协议·http·pytest
小白学大数据4 小时前
Superagent 异步请求:如何处理复杂的 HTTP 场景
开发语言·网络·python·网络协议·http
贺椿椿5 小时前
ensp服务器DNS/HTTP/DHCP配置
linux·服务器·网络·http·智能路由器
给我个面子中不6 小时前
https握手过程
网络协议·http·https
day day day ...7 小时前
Spring Boot 应用的接口访问从 HTTP 改为 HTTPS
spring boot·http·https
智联视频超融合平台7 小时前
大华HTTP协议在智联视频超融合平台中的接入方法
网络协议·http·音视频·实时音视频·视频编解码
编程之升级打怪13 小时前
HTTP服务器的工作逻辑
http
小爬虫程序猿14 小时前
爬虫代码中需要设置哪些HTTP头部信息?
爬虫·网络协议·http
无名之逆1 天前
Hyperlane:Rust 生态中的轻量级高性能 HTTP 服务器库,助力现代 Web 开发
服务器·开发语言·前端·后端·http·面试·rust
等风来不如迎风去1 天前
【python】http post 在body中传递json数据 以发送
python·http·json