大多数情况下, 我们的 Ajax 请求都是通过前端的开发库, 框架发出的, 如 jQuery,axios 或者 Fly. 这些库自身都会有一些请求 / 响应钩子, 用于预处理 Ajax 请求和响应. 但是, 如果你没有使用这些网络库, 又或是你并不是网页的开发者, 而你需要分析某个网页的所有 Ajax 请求, 又或是你是一个应用开发者, 你的 webview 中需要拦截所有网页的网络请求 (网页并不是你开发的)...... 这种时候, 你就需要拦截全局的 Ajax 请求.
原理
无论你的应用是通过那个框架或库发起的 Ajax 请求, 最终都会回归到 XMLHttpRequest . 所以, 拦截的本质就是替换浏览器原生的 XMLHttpRequest . 具体就是, 在替换之前保存先保存 XMLHttpRequest, 然后在请求过程中根据具体业务逻辑决定是否需要发起网络请求, 如果需要, 再创建真正的 XMLHttpRequest 实例.
Fly 拦截全局 Ajax
如果您还不了解 fly, 请参考其官网: https://wendux.github.io/dist/#/doc/flyio/readme
我们知道, 在 Fly 中, XMLHttpRequest 就是一个 http engine https://wendux.github.io/dist/#/doc/flyio/engine . 所以我们要拦截, 只需要自定义一个 engine 替换掉全局的 XMLHttpRequest 就行, 而 Fly 提供了快速生成 engine 的工具, 所以我们可以很方便实现拦截.
我们先看一个简单的例子, 功能是输出每次网络请求 url 和 method.
实现
- var log = console.log;
- // 切换 fly engine 为真正的 XMLHttpRequest
- fly.engine = XMLHttpRequest;
- var engine = EngineWrapper(function (request, responseCallback) {
- console.log(request.url, request.method)
- // 发起真正的 Ajax 请求
- fly.request(request.url, request.data, request)
- .then(function (d) {
- responseCallback({
- statusCode: d.engine.status,
- responseText: d.engine.responseText,
- statusMessage: d.engine.statusText
- })
- })
- .catch(function (err) {
- responseCallback({
- statusCode:err.status,
- statusMessage:err.message
- })
- })
- })
- // 覆盖默认
- XMLHttpRequest = engine;
- axios.post("../package.json").then(log)
我们用 axios 发起一个请求测试一下:
- axios.post("../package.json").then(log)
- // 控制台输出
- > http://localhost:63341/Fly/package.JSON POST
- > {
- data: {
- ...
- }, status: 200, statusText: "OK", headers: {
- ...
- }, config: {
- ...
- }, ...
- }
可以看到控制台中输出了请求的 url 和 method, 我们的拦截成功了. 而 第二行的结果对象是 axios then 打印出的.
因为 Fly 支持切换 engine, 我们可以直接先将 fly engine 切换为真正的 XMLHttpRequest , 然后再覆盖, 这样 fly 中的网络请求都是通过真正的 XMLHttpRequest 发起的 (事实上, 浏览器环境下 fly 默认的 engine 本就是 XMLHttpRequest, 无需手动切换, 此处为了清晰, 故手动切换了一下).fly 会根据 request 对象自动同步请求头. 如果想阻止请求, 直接在 adapter 中 return 即可.
其它拦截方法
GitHub 上的开源库 Ajax-hook 也可以拦截全局的的 Ajax 请求, 不同的是, 它可以拦截 Ajax 请求的每一步, 每一个回调, 不仅强大, 而且也很轻量 (1KB). 和上面通过 fly engine 拦截的方式相比 ,Ajax-hook 的拦截粒度更细, 但 Ajax-hook 由于使用了 ES5 的 getter,setter, 所以不支持 IE9 以下的浏览器.
最后
Fly 刚刚开源, 如果你觉得对您有用, 欢迎 star, 多谢支持 GitHub: https://github.com/wendux/fly
来源: https://www.jb51.net/article/147369.htm