背景
最近公司开新坑,许多接口只有Swagger文档,前端自测的时候需要mock,在网上找了一圈,没找到基于swagger应用场景的mock工具,于是自己动手撸了一个谷歌插件SwaggerMockGenerator,原理也比较简单,就是劫持接口请求,然后根据swagger文档生成数据,并改写接口返回的数据,但就是这么一个劫持接口的方法,我在网上找了一圈,愣是没找到比较好的解决方法,其中大部分写的都是使用chrome提供的background方法,在后台挂载一个监听接口的进程,但由于MV3中background的生命周期不能在后台常驻了,而是插件加载完成后会自动进入休眠状态,只有手动触发才会唤醒,实现起来比较麻烦,所以我想了一个比较简单但是又比较“脏”的方法,接下来是实现方法。
监听接口请求
原理
已知Content Script和原始页面共享DOM,但是不共享JS,所以可以使用Content Script给页面注入一段脚本,利用第三方库ajax-hooks来劫持并篡改接口返回的数据。
实现
使用ajax-hooks监听接口
// inject.ts
import { proxy } from "ajax-hook";
proxy({
//请求发起前进入
onRequest: (config, handler) => {
handler.next(config);
},
//请求发生错误时进入,比如超时;注意,不包括http状态码错误,如404仍然会认为请求成功
onError: (err, handler) => {
handler.next(err);
},
//请求成功后进入
onResponse: (res, handler) => {
const { url, method } = res?.config || {};
try {
// 假设后端有个获取用户信息的接口/accounts/profile
if(url.includes("/accounts/profile" && method.toUpperCase() === "GET")){
// 设置接口状态为200,这样就算后端服务挂了,接口依然可以返回数据
res.status = 200;
// 改变接口的数据
res.response = {
code: 200,
data: {
accountId: "777",
name: "张三",
gender: "男",
like: "唱、跳、rap",
},
message: "success",
};
}
} finally {
handler.next(response);
}
},
});
注入inject.ts脚本
// content-script.ts
const script = document.createElement("script");
script.setAttribute("src", chrome.runtime.getURL("你的inject脚本目录/xxx.js"));
document.head.appendChild(script);
修改Manifest配置
// manifest.json
{
...
content_scripts: [
{
matches: ["http://*/*", "https://*/*", "<all_urls>"],
js: ["你的content脚本目录/xxx.js"],
},
],
...
}
详细的代码可以查看SwaggerMockGenerator
结语
虽然给页面注入脚本的方法不太好,但胜在简单、容易实现,我也尝试使用chrome.webRequest实现过,但是很不稳定,有些接口老是监听不到,所以就分享了这个方法,如果有其他方法,欢迎在评论区里推荐👏🏻。