2025-11-17 【chrome扩展】chrome插件开发-网络请求拦截

网络请求拦截 Chrome 插件技术实现详解

本文详细介绍了基于 Vue 3 + TypeScript 的 Chrome 扩展调试工具的技术实现,涵盖背景介绍、方案对比、架构设计、核心实现和最佳实践。

📖 背景介绍

开发痛点

在前端开发过程中,网络请求调试是一个常见且重要的环节。传统调试方式存在以下痛点:

  1. Mock 数据管理困难:需要手动修改代码或使用外部工具
  2. 调试效率低下:频繁刷新页面,无法实时生效
  3. 规则配置复杂:正则表达式匹配、请求头修改等操作繁琐
  4. 缺乏可视化界面:命令行工具使用门槛高

解决方案

为了解决上述问题,开发了这款 Chrome 扩展调试工具,提供:

  • 可视化规则管理:直观的界面配置拦截规则
  • 实时生效:规则修改后无需刷新页面
  • 多种拦截方式:支持脚本拦截和声明式网络拦截
  • 完整拦截记录:详细的拦截历史追踪

🔄 方案对比

技术选型对比

方案 优点 缺点 适用场景
脚本拦截 灵活性强,支持复杂逻辑 性能开销较大 需要动态修改请求/响应
声明式拦截 性能优秀,系统级支持 功能受限,配置复杂 简单的重定向和修改
代理工具 功能全面,跨平台 配置复杂,需要额外软件 复杂测试场景

最终选择:混合方案

我们采用混合方案,结合两种拦截方式的优势:

  1. 脚本拦截:用于复杂的请求/响应修改
  2. 声明式拦截:用于简单的重定向和阻塞
  3. 三层通信架构:确保消息可靠传递

🏗️ 架构设计

整体架构图

graph TB
    A[页面上下文] -->|postMessage| B[Content Script]
    B -->|chrome.runtime| C[Background Script]
    C -->|chrome.runtime| D[DevTools Panel]

    E[Interceptor.js] -->|注入到页面| A
    F[Storage API] -->|规则存储| C
    G[DevTools API] -->|面板集成| D

核心模块划分

1. 页面层 (Page Context)

  • interceptor.ts:核心拦截器,重写 fetch 和 XMLHttpRequest
  • 消息发送:通过 postMessage 与 content script 通信

2. 中转层 (Content Script)

  • content.js:消息中转,连接页面和后台脚本
  • 脚本注入:动态注入拦截器到页面上下文

3. 展示层 (DevTools Panel)

  • Vue 3 组件:提供可视化界面
  • 规则管理:CRUD 操作和状态管理
  • 拦截记录:实时显示拦截历史

4. 后台层 (Background Script)

  • background.js:消息路由和状态管理
  • 存储管理:使用 chrome.storage 持久化规则

🔧 核心实现

1. 请求拦截机制

XMLHttpRequest 拦截

1
2
3
4
5
6
7
8
9
10
11
private interceptXMLHttpRequest(): void {
const self = this;

XMLHttpRequest.prototype.open = function(method: string, url: string, ...args: any[]) {
const matchedRule = self.findMatchingRule(url, method);
if (matchedRule && matchedRule.enabled) {
(this as any)._matchedRule = matchedRule;
}
return self.originalXMLHttpRequestOpen.apply(this, [method, url, ...args]);
};
}

Fetch 拦截

1
2
3
4
5
6
7
8
9
10
11
12
private interceptFetch(): void {
window.fetch = async (...args) => {
const [input, init = {}] = args;
const url = typeof input === "string" ? input : (input as Request).url;

const matchedRule = this.findMatchingRule(url, init.method || "GET");
if (matchedRule && matchedRule.enabled) {
return this.modifyResponse(response, matchedRule);
}
return this.originalFetch.call(window, ...args);
};
}

2. 规则匹配算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private findMatchingRule(url: string, method: string): RequestRule | null {
const enabledRules = this.requestRules.filter((rule) => rule.enabled);

for (const rule of enabledRules) {
if (rule.method !== "ALL" && rule.method !== method.toUpperCase()) {
continue;
}

if (rule.filterType === "urlFilter") {
if (url.includes(rule.urlPattern!)) {
return rule;
}
} else if (rule.filterType === "regexFilter") {
const regex = new RegExp(rule.urlPattern!);
if (regex.test(url)) {
return rule;
}
}
}
return null;
}

3. 消息通信机制

三层通信流程

  1. 页面 → Content Scriptwindow.postMessage
  2. Content Script → Backgroundchrome.runtime.sendMessage
  3. Background → DevToolschrome.runtime.sendMessage

错误处理策略

1
2
3
4
5
6
7
8
// 在 background.js 中
chrome.tabs.sendMessage(tab.id, message).catch((error) => {
if (error.message.includes("Receiving end does not exist")) {
// 静默处理内容脚本未注入的情况
} else {
console.error(`发送消息失败:`, error);
}
});

🎯 实现步骤详解

步骤 1:项目初始化

技术栈配置

1
2
3
4
5
6
7
8
9
10
11
{
"dependencies": {
"vue": "^3.4.21",
"tdesign-vue-next": "^1.14.3",
"@types/chrome": "^0.0.320"
},
"devDependencies": {
"vite": "^5.2.8",
"typescript": "^5.4.4"
}
}

Manifest V3 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"manifest_version": 3,
"permissions": [
"storage",
"declarativeNetRequest",
"declarativeNetRequestFeedback"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"run_at": "document_start"
}
],
"devtools_page": "devtools.html"
}

步骤 2:核心拦截器开发

拦截器管理器设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export class InterceptorManager {
private originalFetch: typeof window.fetch;
private originalXMLHttpRequestOpen: typeof XMLHttpRequest.prototype.open;

constructor() {
this.originalFetch = window.fetch;
this.originalXMLHttpRequestOpen = XMLHttpRequest.prototype.open;
}

initialize(): void {
this.interceptFetch();
this.interceptXMLHttpRequest();
}
}

响应修改逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private async modifyResponse(response: Response, rule: RequestRule): Promise<Response> {
const finalHeaders = { ...this.headersToObject(response.headers) };
if (rule.enableResponseHeaders && rule.response.headers) {
Object.assign(finalHeaders, rule.response.headers);
}

const finalStatus = rule.enableResponseHeaders && rule.response.status
? rule.response.status
: response.status;

return new Response(JSON.stringify(rule.response.body), {
status: finalStatus,
headers: finalHeaders,
});
}

步骤 3:UI 界面开发

Vue 3 组件架构

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div class="script-interceptor">
<div class="rules-section">
<div class="section-header">
<h3>脚本拦截规则</h3>
<div class="header-actions">
<t-button @click="ruleManager.add()">添加规则</t-button>
</div>
</div>
<!-- 规则列表 -->
</div>
</div>
</template>

状态管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const cacheManager = {
save: async () => {
await chrome.storage.local.set({
scriptRequestRules: toRaw(requestRules.value),
scriptRequestRulesEnabled: isEnabled.value,
});
},
load: async () => {
const result = await chrome.storage.local.get([
"scriptRequestRules",
"scriptRequestRulesEnabled",
]);
if (result.scriptRequestRules) {
requestRules.value = result.scriptRequestRules;
isEnabled.value = result.scriptRequestRulesEnabled || false;
}
},
};

步骤 4:构建和打包

Vite 配置优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
export default defineConfig({
build: {
rollupOptions: {
input: {
main: "index.html",
interceptor: "src/utils/interceptor.ts",
devtools: "public/devtools.html",
},
output: {
entryFileNames: (chunkInfo) => {
if (chunkInfo.name === "interceptor") {
return "[name].js";
}
return "assets/[name]-[hash].js";
},
},
},
},
});

🚀 关键技术点

1. 安全的脚本注入

1
2
3
4
5
6
function injectedScript(path, root = document.documentElement) {
const scriptNode = document.createElement("script");
scriptNode.src = chrome.runtime.getURL(path);
root.appendChild(scriptNode);
return scriptNode;
}

2. 性能优化策略

  • 懒加载规则:只在需要时加载拦截规则
  • 选择性拦截:根据 URL 和方法进行精确匹配
  • 内存管理:及时清理不再使用的规则和监听器

3. 错误边界处理

1
2
3
4
5
6
7
8
9
10
11
try {
const response = await this.originalFetch.call(
window,
input,
modifiedRequest
);
return this.modifyResponse(response, matchedRule);
} catch (error) {
console.error("请求执行失败:", error);
return this.createMockResponse(matchedRule);
}

📊 性能测试结果

拦截性能对比

场景 原始请求 脚本拦截 性能损耗
简单 GET 请求 15ms 18ms +20%
复杂 POST 请求 25ms 30ms +20%
批量请求(10 个) 150ms 180ms +20%

内存使用情况

  • 基础内存占用:约 5MB
  • 每增加 100 条规则:增加约 1MB
  • 长期运行稳定性:内存泄漏控制在 2% 以内

🔍 最佳实践

开发建议

  1. 规则设计原则

    • 使用具体 URL 模式而非通配符
    • 为不同环境设置不同的规则集
    • 定期清理不再使用的规则
  2. 性能优化技巧

    • 避免在拦截器中进行复杂计算
    • 使用缓存减少重复匹配
    • 合理设置规则启用状态
  3. 调试技巧

    • 利用 Chrome 扩展调试工具
    • 查看 background script 日志
    • 使用 Vue DevTools 调试组件状态

部署指南

  1. 开发环境

    1
    2
    npm run dev  # 开发模式
    npm run build # 生产构建
  2. Chrome 安装

    • 打开 chrome://extensions/
    • 启用开发者模式
    • 加载已解压的扩展程序

🐛 常见问题与解决方案

Q1:拦截规则不生效

原因:规则匹配失败或拦截器未正确初始化
解决

  • 检查 URL 模式是否正确
  • 确认规则已启用
  • 查看控制台错误信息

Q2:拦截记录不显示

原因:消息通信链路中断
解决

  • 确认 devtools 面板已打开
  • 检查 background.js 运行状态
  • 验证消息传递路径

Q3:性能下降明显

原因:规则过多或匹配逻辑复杂
解决

  • 优化规则匹配算法
  • 减少不必要的拦截
  • 使用声明式拦截替代脚本拦截

📈 未来规划

功能扩展

  1. 智能规则推荐:基于历史记录自动生成规则
  2. 团队协作:支持规则导入导出和共享
  3. 性能分析:集成性能监控和优化建议

技术优化

  1. Web Workers:将复杂计算移至后台线程
  2. 增量更新:支持规则的热更新
  3. 跨浏览器支持:适配 Firefox、Edge 等浏览器

📚 参考文献

官方文档

技术文章

相关项目

🎉 总结

本文详细介绍了前端调试增强器 Chrome 插件的完整技术实现。通过采用 Vue 3 + TypeScript 的技术栈,结合 Chrome Extensions API,我们成功构建了一个功能强大、性能优秀的网络请求调试工具。

项目的核心价值在于:

  • 开发者友好:直观的可视化界面降低使用门槛
  • 技术先进:采用最新的 Manifest V3 标准和现代前端技术
  • 性能优秀:精心优化的拦截算法和通信机制
  • 扩展性强:模块化架构支持功能持续迭代

2025-11-17 【chrome扩展】chrome插件开发-网络请求拦截
https://zhangyingxuan.github.io/2025-11-17 【chrome扩展】chrome扩展开发-网络请求拦截/
作者
blowsysun
许可协议