一条通配符规则,落到实处是这样
改一组地址试试 →- 匹配模式
https://fat-api.example.com/*- 目标地址
https://uat-api.example.com- 页面发起
https://fat-api.example.com/api/user/list- 实际发出
-
https://uat-api.example.com/api/user/list网络层改写 · 单请求零 JS 开销
跨域代理助手是一款开源 Chrome 扩展(Manifest V3),把页面发出的 API 请求代理到另一个后端环境。重写 URL、请求头与响应,条件化 Mock、注入延迟、阻断请求、失败重试、转发 WebSocket——全部在浏览器里配置,数据只存在你的电脑上。
需要较新版本的桌面 Google Chrome(Manifest V3)。推荐通过 Chrome Web Store 安装,也可以从源码构建或下载预构建包。
fetch / XMLHttpRequest / WebSocket;被阻断的请求绝不回退重放。
一条通配符规则,落到实处是这样
改一组地址试试 →https://fat-api.example.com/*https://uat-api.example.comhttps://fat-api.example.com/api/user/listhttps://uat-api.example.com/api/user/list
网络层改写 · 单请求零 JS 开销
跨环境调试通常要付出三种成本之一:改后端、每个项目改一次配置,或者本地伪造一套构建。这款扩展把这三者收敛成一条浏览器规则,并对你打开的每个页面生效。
| 没有扩展时 | 有了一条规则后 |
|---|---|
| 改 devServer 代理表,然后重启开发服务——每个项目一次,同事还看不到。 |
添加 https://fat-api.example.com/* →
https://uat-api.example.com,立即对浏览器里的所有项目生效。
|
请后端把你的源加进 Access-Control-Allow-Origin 并重新发布。 |
带任一高级能力的请求由扩展应答,页面侧 CORS 校验不会触发。 |
| 在源码里硬写另一个环境的 token,还得记得改回去。 | 按规则注入请求头,调试完把规则关掉即可。 |
| 等一个还没写完的接口,或者在应用里塞桩代码。 | 在规则里 Mock——还能按 URL、方法、查询参数返回不同内容。 |
| 抓包工具里录下流量,再手工复现一次请求去验证异常分支。 | 导入 HAR / OpenAPI 文档,或粘贴 cURL 命令,规则自动预填。 |
CORS 不是一种错误,而是一族。按
MDN 的 CORS 说明,浏览器在三处分别校验:实际请求的响应头、预检(OPTIONS)的放行名单、以及带凭据时的严格模式。三句共享同一个前缀
Access to fetch at '<目标地址>' from origin '<你的源>' has been blocked by CORS
policy,差别全在后半段——拿整串去搜往往什么都搜不到,抓后半段那一句才准。
No 'Access-Control-Allow-Origin' header is present on the requested resource.
后端没有把 fat-web.example.com 回进
Access-Control-Allow-Origin。让这条规则带上任一高级能力,请求改由扩展代发,页面侧根本不触发这道校验。
Request header field "x-token" is not allowed by Access-Control-Allow-Headers in preflight
response.
预检被回答得太窄:你加的不是简单请求允许的头部集合,而后端只回
Content-Type。这类报错和「后端没放开」不是一回事——把自定义请求头配到规则里由扩展注入,页面就压根不发
OPTIONS。
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*'
when the request's credentials mode is 'include'.
带 Cookie 时最严:此时 Access-Control-Allow-Origin 不能是
*,必须逐字是你的源。这就是「同源什么都好,一换环境就 401」最常见的成因。
匹配模式、目标地址与优先级是一条规则的骨架。其余能力都是可选且可叠加的——而你开启的每一项能力,同时也决定了这条规则走哪条通道。
仅重写 URL 的规则会被编译为
declarativeNetRequest
动态重定向,由浏览器网络栈完成,单请求零 JavaScript 开销——对
XHR、页面跳转、内联框架、脚本、样式、图片、字体与媒体资源同样生效。更复杂的规则走后台服务线程:主世界拦截器接管
fetch、XMLHttpRequest 与 WebSocket,经
隔离世界的内容脚本
桥接,再把响应交回页面。
重写 URL;注入或替换请求头;替换请求体;改写响应状态码、状态行文本与响应头,按点分路径(如
data.token)替换 JSON
字段,或整段替换响应体——后者非空时优先于按字段改写。头名会做合法性校验、值里的 CRLF
会被直接拒收,规则无法构造请求拆分;Mock 与改写的状态码被钳制在 200–599,保证页面总能构造出合法响应。
三种匹配类型:*
匹配任意字符、前缀匹配开头、正则整体匹配且目标地址可引用捕获组。通配符与前缀在两条通道上的重写结果完全一致;正则只有覆盖整个
URL 时才一致——网络层整条替换
URL,后台通道只替换模式命中的那一段。正则规则的表单会把模式里的捕获组和目标地址里的
$n 引用逐条对照出来,编号越界、以及网络层读不动的
\9 以上都当场标出(只提示,不拦保存)。用户正则会先做嵌套量词 ReDoS
筛查,送往网络层的正则还要通过 Chrome 的
RE2
校验。
不碰任何服务器,直接返回构造好的 JSON / 文本 / HTML / XML 与状态码;还可以挂多组条件(URL 正则、方法、查询参数),首个命中的条件决定响应内容。一条规则就能替整组接口,或同一接口的多种状态。
注入 0–60000 毫秒延迟验证骨架屏与超时;把请求阻断成网络错误;或让扩展在一次失败或 5xx 之后追加 1–5 次尝试,间隔可在 100 至 30000 毫秒之间设置。
把规则限定在 GET / POST / PUT / DELETE / PATCH / OPTIONS / HEAD
中的若干方法(例如只把写操作打到测试后端),或者不改写地址、只在最终 URL 上追加或覆盖查询参数,如
__env=uat 与灰度标识。
通过重写 socket 地址把 ws:// 与 wss:// 连接指向另一个环境,让实时业务跟 REST
一起切换环境。匹配模式可以用 http(s) 也可以写 ws(s),方法过滤把握手视为
GET。长连接上生效的只有地址重写、查询参数注入与阻断——请求头、请求体与响应改写、Mock、延迟、重试、携带
Cookie 都不适用于它,规则列表里的 WS 徽标悬停时会把这句边界说明白。
规则列表为空时可从快速模板起步,复制规则、拖拽调整优先级、批量启停与删除,删除后还可撤销。关键词可搜名称、匹配模式与目标地址,再配合状态与匹配类型下拉进一步收窄列表。当同模式的更高优先级规则会把当前规则遮蔽时,编辑时会给出冲突提示,避免写下一条永远不会命中的规则。而浏览器网络层根本不会应用的规则——RE2
不支持的正则语法、越界的捕获引用——会在列表里直接标为「未生效」。规则还能打标签:一条最多 10
个,只做分类与筛选,不参与匹配、分流与任何判定,也不会出现在交给页面脚本的那一份规则里(桥接层把它与凭据字段一起剥掉才下发),所以加一个标签不会改变任何一条请求的走向;列表露两枚、其余收成
+N,筛选栏那一格按标签多选是「任一命中」,另有「(无标签)」专门捞出还没分类的那批。
URL 匹配测试器可实时预览任意
URL(可带方法)的命中规则、重写结果、转发通道、额外动作,以及同样命中但被它遮蔽的规则。请求日志保留最近
500 条,含方法、状态、耗时与命中的规则,可按方法、状态区间、规则名或 URL
关键词筛选,详情可看请求与响应的头与文本 body(二进制响应体不落盘),可按原始请求地址复制为
cURL,并展示两条通道各自的命中数。详情里 Authorization / Cookie 这类会带出会话的头,值默认打码(长值留尾
4
位),要对着原值排障时再手动展开,关掉抽屉即收回。详情里还有一颗「重放这一笔」:把这条记录自己的地址、方法、请求头与正文交回代理引擎,按现在生效的规则真的再发一次——总开关、站点生效范围、规则匹配、Mock
/ 阻断 / 延迟 /
重试与凭据展开全部再走一遍(这一笔没有发起页主机可判,所以「只让名单内站点生效」那一档下它不会代发),扩展不必(也不该)自己另算一份「代理会怎么做」;GET
/ HEAD / OPTIONS
直接发,其余方法先确认一句「这会真的再发一次」,结局也不是「成功 /
失败」两种而是十一档各说各话,记录里任何一个字段带过截断标记的那一条不发。弹窗动作区那颗「自检」(配置页也可直接开
#self-check)则把散在四处的判据排成一屏:总开关、这一台站点在不在生效范围、后台有没有记下「这一页没收到最近一次配置推送」、这一页的地址命中哪条规则与走哪条通道、网络层规则有没有真的装进浏览器——每一格只复述一个已经在别处算过的判据,读不到或还没判完的,分别画「不知道」与「还没定」,不替上面任何一步编一个答案。
JSON 配置导出,默认开启分享模式,自动剔除 Authorization、Cookie 等请求头/响应头与 token
类查询参数,取消勾选即原样备份;导入时可选择覆盖或与现有规则合并,写入前还能先预览这个文件会新增几条、
哪些同名同模式的旧规则被保留(预览与写入同一份判据);HAR 1.2 导出捕获到的流量,导入 HAR
则把录制到的请求自动变成规则(填了目标环境才默认启用,否则停用等你确认);导入 OpenAPI / Swagger
文档会按它声明的 `servers` 逐条建规则(读不出的来源跳过并点名);粘贴 cURL
预填表单;每条日志都能按原始请求地址复制为 cURL。环境快照保存整套规则的命名副本,FAT / UAT / PROD
不用先开配置页——弹窗里点「环境配置」就列出已存的快照,点一下那一行、再确认一次就整套换过去(换之前先把当前配置记成一份恢复点,也会把总开关打开);环境换域名时,批量迁移会先给出变更预览;覆盖导入、加载快照、真正删掉了东西的批量删除这三类整套替换,会把自己换掉的那份规则集留在「设置
→ 配置恢复点」里(最近 5 份),随时一键回退。请求头与查询参数的值还能写成
{{UAT_TOKEN}} 这样的引用,真值单独存在「设置 →
凭据变量」表里——规则本身、导出的配置与环境快照、下发给页面的配置都只带这个引用,换出真值发生在扩展代发请求的最后一刻。
弹窗里集中了总开关、启用规则数、经扩展请求数(只统计后台通道)、本页近 5
分钟的网络层命中数、最近请求、规则快捷启停、自动关闭档位与倒计时、本页地址命中预览、动作区那一颗「自检」,以及「为当前页创建规则」——点后者时先看这一页自己发过哪些请求(本地
performance 条目里的 fetch/XHR
来源,最多六项),把接口地址列出来让你挑,而不是只把页面地址抄进规则;这一页问不到任何接口时,仍旧按页面地址预填。而如果这一页上有请求像是被跨域拦下——没有任何规则覆盖的原生
XHR 以 error + status === 0 失败——那个来源会带「疑似 N
笔」标记排在最前,卡片那行说明也会在你点开之前先说「检测到 N 个来源的请求像是被跨域拦下」。被 CORS
拦下、断网、DNS
失败、连接被拒在页面上是同一个形状,扩展分不出这四者,所以它是帮你排顺序的线索而不是结论;这份数由页面自己上报、只存内存、不参与任何判定。数据行下方按需出现一行「页面自报」:那是一句话,只露两个数——这一页的
JS
层拦到多少、其中多少交给后台代发(有回退时改说回退成了原生请求多少,没有回退但有超时时说的是多少个没等到响应),有读数时悬停才展开四个数与上报时刻,并注明同一请求可同时计入多项、不能相加,四个数按本次文档累计、导航即归零。回退与超时原本只在控制台留一行日志,而「一次都没拦到」与「这个页面本来没请求」在此之前长得一模一样。这四个数由页面自己上报、可被同页脚本伪造,所以只做诊断线索、不参与任何判定,措辞也始终写明是「自报」。工具栏角标显示代理状态;自动关闭(30
分钟至 4 小时,基于 chrome.alarms)会到点关掉总开关,忘了关的代理不会活过调试本身。
中英文界面、6 套主色配浅色/深色/跟随系统,弹窗、配置页与页面内组件同步切换;键盘快捷键:⌘⇧P 开关代理、N 新建规则、/ 聚焦搜索、Esc 关闭。单键快捷键是有意为之——⌘/Ctrl+N 会被浏览器保留用于新建窗口,页面捕获不到。
以下均为当前版本的真实截图(演示数据为 fat-api.example.com →
uat-api.example.com,不含任何真实内网地址)。配置页承载规则表、匹配测试、请求日志与导入导出;弹窗把总开关与当前页预览放在一步可达的位置;凭据变量表让
token 只在本机存一份。
每条启用的规则在每次配置同步时从存储里重新分类。是这个分类决定请求由浏览器网络栈还是扩展后台应答,匹配测试器展示给你的也就是它的结果。总开关管着两条通道:关掉时网络层规则被整体清空,后台通道也原样放行请求。
| 能力 | 为什么网络层做不到 |
|---|---|
| 请求头 / 请求体覆盖 | 替换请求体需要重新发一次真实请求,而不是重定向。 |
| 响应状态码 / 响应头 / JSON 字段覆盖 | 响应需要先读出来、再重建。 |
| Mock(含或不含条件)、延迟、阻断、重试 | 它们改变的是请求到底会不会发生、何时发生、发生几次。 |
| HTTP 方法过滤 | 重定向规则无法按请求方法做条件。 |
| 查询参数注入 | 在重写之后才应用,重定向替换无法表达。 |
WebSocket(ws:// / wss://) |
declarativeNetRequest 没有 WebSocket 资源类型。 |
不以 * 结尾的通配符,或目标地址为空 |
强行替换会静默丢弃尾部固定文本,或产生非法的重定向值。 |
后台通道的请求由持有主机权限的扩展发出,页面拿到的是扩展构造的响应,因此不会触发页面侧 CORS 校验。仅重写 URL
的请求仍是一次普通的跨域请求:浏览器对重定向后的响应套用同源策略,依然要求
Access-Control-Allow-Origin
覆盖你的源。若目标环境不允许你的源,给规则加上任一能力(加一个响应头覆盖代价最小),它就换到后台通道。
拦截失败时,页面会回退到原生的 fetch、XMLHttpRequest 或
WebSocket;FormData、Blob、ArrayBuffer
等非字符串请求体也走原生路径,而不是静默丢体。阻断规则是刻意保留的例外:被阻断的请求绝不回退重放,否则发出去的就是你要压掉的那个请求。
chrome.storage.local
是唯一事实源。后台服务线程内的缓存——编译好的正则、规则列表、命中计数——均可重建,并在每次配置变更时失效,因此服务工作线程重启后扩展行为依旧正确。
无需注册、无需服务器、无需安装证书。从克隆到第一条代理请求大约一分钟。
需要 Node.js 20+ 与 pnpm 10。不想装工具链?每个打 tag 的版本都会在 Releases 附上预构建 zip,解压即可——先确认那里已有发布记录。
git clone https://github.com/liaolongdong/cross-origin-proxy
cd cross-origin-proxy
pnpm install
pnpm build
打开 chrome://extensions,开启右上角「开发者模式」,点击「加载已解压的扩展程序」并选择
.output/chrome-mv3(或刚从 Releases 解压出来的目录),建议把图标固定到工具栏。
https://fat-api.example.com/* → https://uat-api.example.com。
刷新页面。像示例里这种通配符重写发生在浏览器网络层,不会产生逐条请求日志:请在 URL 匹配测试器里预览这条地址,并看规则的 DNR 命中数。只有走后台通道的请求才会出现在请求日志里。
下面这一格跑的是扩展里同一套匹配与重写判据,改四个输入就能当场看到结果。它不联网,输入的字符也不离开这个页面。
两行不一样不是坏在谁身上:后台通道只把匹配到的那段字符换掉,网络层则是整个地址被替换成替换串。走哪一行,看上面点名的那条通道。
这一笔已经通过预演,可以连同模式和目标一起带走:
用法:装好扩展后打开配置页 → 「导入/导出配置」→ 把这段 JSON 贴进「或直接粘贴 JSON 配置」那一栏导入。它只带这一条规则(规则本身是启用的),而代理总开关保持关闭——要不要开,由你确认后决定。
.json 文件。这条规则本身是启用的,但文件不会替你打开总开关:如果代理还关着,在弹窗里打开即可。配置里只有匹配类型、匹配模式与目标地址,没有任何请求头或凭据。
*:网络层的替换串只能引用捕获组,会丢掉末尾那段固定文本,所以这条改走后台通道——而后台通道
的重写同样只认末尾的那个 *,上面那一行因此还是原地址:这一笔按原样代发,改的是头、体与
Mock,不是地址。
还剩一件事只能交给扩展自己判:这条网络层规则会不会被 Chrome 的 RE2 引擎接受,网页里这一格调不到那个 API,正则模式请以设置页里的「未生效」标记为准。
更新解压版构建时:请覆盖原目录里的文件。换一个目录加载会被 Chrome
视为一次全新安装并分配到不同的扩展 ID,而规则、日志与环境快照在 chrome.storage.local 中按 ID
隔离存放——旧规则看起来就空了。
从场景到配置的最短路径。下表每一行都是扩展已实现的行为,不是变通方案。
| 场景 | 规则配置 | 通道 |
|---|---|---|
| 在 FAT 页面上验证只有 UAT 才有的修复 | 把 API 前缀通配符重写到 UAT 域名。 | DNR |
| 后端接口还没写,先把 UI 做出来 | Mock 响应自定内容与状态码;用条件让不同接口返回不同内容。 | SW |
| 验证加载态与超时分支 | 对具体接口注入 3000–60000 毫秒延迟。 | SW |
| 验证离线兜底与 500 错误页 | 阻断请求,或改写响应状态码。 | SW |
| 上游不稳定,希望读接口更韧性 | 重试 2–5 次,间隔 1000 毫秒。 | SW |
| 命中灰度 / A/B 分支 | 查询参数注入,如 __env=uat。 |
SW |
| 只把写操作打到测试后端 | 方法过滤只允许 POST / PUT / DELETE。 |
SW |
| 在另一个环境调试实时功能 | 把页面的 socket 地址重写到目标 socket。 | SW |
| 页面因为某个字段缺失而报错 | 按点分路径替换 JSON 字段,如 data.token → "mock-token"。 |
SW |
| 目标环境不允许你的源 | 加上任一能力(如响应头覆盖)即可离开网络层。 | SW |
| 把同一套配置交给同事 | 导出 JSON(分享模式默认剔除凭据),或分享由 HAR 衍生的规则集。 | — |
| 环境换了新域名 | 批量迁移目标地址,并先查看变更预览。 | — |
表头是工具类别而非具体产品:同一类里的能力差异很大,请以你在用的工具实际文档为准。
| 方案 | 本扩展 | 开发服务器代理 | 抓包代理工具 | API 客户端 / 改头类扩展 | 改应用配置 |
|---|---|---|---|---|---|
| 需要后端或网关配合改动 | 不需要 | 为 CORS 常常需要 | 不需要 | 不需要 | 不需要 |
| 需要逐个项目配置 | 否——全浏览器共用 | 是 | 系统级配置 | 按规则集 | 是 |
| 对任意页面源生效(localhost、内网系统) | 是 | 仅指向该开发服务的流量 | 是 | 受扩展 API 限制 | 是 |
| 改写响应(状态码、响应头、JSON 字段) | 支持 | 不支持 | 支持 | 响应体通常不行 | 不支持 |
| 界面里直接 Mock / 延迟 / 阻断 / 重试 | 支持,含条件化 Mock | 需额外插件 | 支持 | 通常只有 Mock | 不支持 |
| 覆盖 WebSocket 流量 | 支持 | 较少见 | 支持 | 不支持 | 不支持 |
| 读 HTTPS 需要本地 CA 证书 | 不需要——在浏览器内运行 | 不需要 | 需要 | 不需要 | 不需要 |
| 规则可用普通本地文件分享 | JSON / HAR / OpenAPI / cURL | 随仓库代码共享 | 会话文件 | 常需云端同步 | 随仓库代码共享 |
| 能代理服务端到服务端等非浏览器流量 | 不能——仅浏览器范围 | 不能 | 能 | 不能 | 看情况 |
代价说在明处:它是一个浏览器内的工具。它无法帮助服务端之间的调用,不会把任何内容录到云端工作区,规则也存在你的 Chrome 配置文件里而不是共享的项目文件中——想给同事一份,就导出 JSON。抓包代理工具适合系统级流量,而本扩展适合「这个页面应该去连那个环境」。
较新版本的桌面版 Google Chrome(Manifest V3)。推荐通过
Chrome Web Store
安装;也可以从源码构建并加载
.output/chrome-mv3,或加载从
Releases
下载的预构建 zip。Edge 支持 Chromium 扩展,同一构建通常可用;Firefox 因为
declarativeNetRequest 差异目前不是支持目标。与其他扩展一样,chrome://
页面、应用商店与其他扩展页面无法注入。
Node.js 20 及以上、pnpm 10(见 packageManager)。技术栈为
WXT
+ Vue 3 + TypeScript + Element Plus + Vite,Element Plus
按组件引入以控制包体;匹配、重写与导入导出逻辑由 Vitest 覆盖。
pnpm dev # WXT 开发服务,带热更新(端口 8899)
pnpm build # 生产构建 → .output/chrome-mv3
pnpm build:zip # 商店上传用 zip
pnpm test # vitest 单元测试
pnpm typecheck # tsc --noEmit
pnpm lint # eslint
pnpm lint:style # stylelint
pnpm assets # 重新生成商店与落地页图片
所有内容都存在本机的
chrome.storage.local。没有账号、没有统计埋点、没有遥测、没有自有远程服务:唯一的网络流量就是你让它代理的 API
流量。日志与导出均在本地生成——也需要提醒一句:日志会记录被代理的请求内容(请求头可能含 token),分享导出的
HAR 或 cURL 前请先检查。阅读隐私政策。
| 权限 | 为什么需要 |
|---|---|
storage |
持久保存规则、凭据变量、请求日志、环境快照、配置恢复点与偏好设置。 |
declarativeNetRequest |
安装网络层重定向规则,让简单改写做到单请求零 JS。 |
declarativeNetRequestFeedback |
读取哪些重定向规则真正命中,用于日志抽屉里的命中统计。 |
alarms |
代理期间维持后台服务工作线程,并运行自动关闭倒计时。 |
<all_urls> 主机权限 |
代理必须在你前端运行的任意源上生效;目标环境是开发者自己的内网域名,无法提前枚举。 |
| 约束 | 取值 |
|---|---|
| 规则数 | 新增、批量新增与合并导入时最多 200 条;替换式导入按文件内容原样写入 |
| 凭据变量 | 最多 50 条(名称 ≤ 64 字符、值 ≤ 4096 字符) |
| 配置恢复点 | 最近 5 份整套规则快照,合计控制在约 100 万字符预算内 |
| 导入文件 | 最大 2 MB,超限在读取文件之前拒绝并说明原因,不做部分读取 |
| HAR 条目 | 单次导入最多 5000 条,超限在转换成规则之前拒绝(配置页与后台各判一次) |
| 请求日志 | 最近 500 条(环形缓冲) |
| 请求体 | 最大 10 MB |
| 回包正文 | 最大 10 MB,越界判失败且不截断(fetch 回退原生再发,XHR 以 status 0 报错) |
| 注入延迟 | 0 – 60000 毫秒 |
| 重试 | 0 – 5 次,间隔可配 |
| 单请求超时 | 30 秒 |
| Mock / 改写的状态码 | 钳制在 200 – 599 |
| 自动关闭 | 30 分钟 / 1 小时 / 2 小时 / 4 小时 |
页面内容也是机器可读的:同样的问答以 FAQPage 结构化数据发布,llms.txt
则向 AI 助手概述这款产品的能力与架构。
它拦截页面发出的 API 请求,并把请求送到别处。在研发场景里,通常就是让一个连着某个后端的前端页面改连另一个环境,于是不改应用代码、不重新部署,也能在 FAT 页面上验证只有 UAT 才有的修复。
页面主世界的拦截器会接管 fetch、XMLHttpRequest 与
WebSocket,相对地址在匹配前先解析为绝对地址。仅重写 URL 的规则会被编译成
declarativeNetRequest
重定向,由浏览器对匹配的各类资源生效:主文档与子框架、XHR、脚本、样式、图片、字体、媒体与其他。
通配符把 * 视为任意字符,并把结尾 * 捕获的内容拼接到目标地址之后;前缀匹配 URL
开头,把剩余部分拼到目标之后;正则要覆盖整个 URL
才能让两条通道结果一致——后台通道只替换模式命中的那一段,网络层则整条替换,因此建议用
^ 锚定并把结尾写成
(.*)$。多条规则同时命中时,优先级数值小者优先,数值相同则按规则列表里的先后顺序,请给每条规则不同的数值。
内容脚本注入到所有 http 与 https 页面,规则按请求 URL
匹配,因此内网系统、localhost 开发服务、预发域名都适用。chrome:// 页面、Chrome
应用商店与其他扩展页面被浏览器统一限制,任何扩展都无法注入。
使用了任一高级能力(请求头覆盖、请求体覆盖、响应覆盖、Mock、延迟、阻断、重试、方法过滤、查询参数注入、携带
Cookie、WebSocket)的规则,由持有主机权限的扩展后台上下文发出请求,页面拿到的是扩展构造的响应,因此不会触发页面侧的
CORS 校验。仅重写 URL 的规则走网络层重定向,浏览器仍会校验重定向后响应的
Access-Control-Allow-Origin。若目标环境不允许你的源,给规则加上任一高级能力(加一个响应头覆盖代价最小)即可切到后台通道。
这是网络层的一条硬边界,实测 Chrome 155:把请求改写到
另一个原点
的纯 URL 重写规则,目标收到的
Origin
是
null,不是你页面自己的源;改写后仍落在同一原点内的规则不受影响。Origin
成了 null,按来源白名单放行的后端就会拒掉这一笔,哪怕它本来就允许你的前端域名,页面侧表现为
net::ERR_FAILED。两条解法:让落点环境放行任意来源,或者给规则加一项高级能力(响应头覆盖代价最小)切到后台代发——后台那一次请求由扩展自己发出,页面侧的
CORS 校验根本不参与。
因为网络层表达不了你想要的行为。不以
*
结尾的通配符、目标地址为空,或者带了任一高级能力,都会被刻意路由到后台通道——若强行编译成重定向,结果会被悄悄改变。URL
匹配测试器会在你依赖某条规则之前,把任意 URL 的转发通道显示出来。
只重写 URL 的规则单请求零 JavaScript 开销,由浏览器网络栈直接完成重定向。走后台通道的请求会多一次扩展内的中转,外加你配置的延迟,单个代理请求有 30 秒上限。用户编写的正则会先做嵌套量词 ReDoS 检测,送往网络层的正则还需通过 Chrome 的 RE2 校验——一条不支持的正则会让整批规则安装失败,因此在同步前就被过滤掉。
网络层重定向不会经过扩展,没有可记录的逐条请求。规则级命中数会出现在「DNR 命中统计」里,统计窗口为最近 5 分钟;Chrome 对该读取接口有配额限制,因此面板按需刷新,超出配额时保留上一次结果并标出统计可能有延迟。后台通道的命中数单独统计。
按这个顺序看:弹窗里的总开关是否开启(关闭时网络层规则会一并卸载)→ 这条规则本身是否处于启用状态 →
这一页是否重新加载过,已经发出的请求不会被追溯改写 → 在「URL
匹配测试」里输入实际请求地址,看它是否被一条优先级更靠前(数字更小)的规则遮蔽 → 用正则时确认它覆盖整条
URL:网络层用替换结果整体替换
URL,后台通道只替换命中的片段,覆盖不全的正则在两条通道上结果不同——扩展里的「URL
匹配测试」会把两个地址一起摆出来,指着那一格说清是在哪一步分的岔。复杂规则还多一处可看——后台确实记下「这一页没接到那次配置推送」时,弹窗会出现一句「此页尚未收到最新配置,刷新这一页通常可恢复」,句子右边就有一枚「刷新这一页」按钮(只在这一次真的问到那一页时才出现,点它等于按浏览器自己的刷新),悬停进一步点名是哪种原因:这一页早于扩展的安装
/ 更新 / 重载打开(刷新即可),或该站点禁用了扩展(要在 Chrome
的扩展菜单里为它重新开启)。这句只说它有把握的事:非 http(s)
页、正在加载的文档、以及从没记过这笔账的页面统统保持沉默。还有一种情况是这一页压根没有规则覆盖它:弹窗的「为当前页创建规则」会先把哪几个来源像是被跨域拦下说出来(那些来源在候选里带「疑似」标记、排在最前),读的是这一页自己报错、却没有被任何规则接住的原生请求;被
CORS 拦下、断网、DNS
失败在页面上是同一个形状,所以它是帮你排顺序的线索,不是结论。想一次问完而不是逐条排查,可以按弹窗动作区那颗「自检」(配置页也可直接开
#self-check):一屏按上面这个顺序摆出五个现成读数——总开关、这一台站点在不在生效范围、后台有没有记下「这一页没收到最近一次配置推送」、这一页的地址命中哪条规则与走哪条通道、网络层规则有没有真的装进浏览器;每一格只复述一个已经在别处算过的判据,读不到或还没判完的,分别画「不知道」与「还没定」,不会替上面任何一步编一个答案。
一条规则可以挂多组条件——URL 正则、HTTP 方法、查询参数——首个命中的条件决定响应体、状态码与 Content-Type,全部不命中时回落到规则的默认响应体。于是一条规则就能替多个接口、或同一接口的多种状态兜底。Mock 请求完全不触网,返回状态码被钳制在 200–599。
阻断让请求以网络故障的方式失败,用来验证离线兜底与重试逻辑;改写响应状态码则给你一个真实的 HTTP 错误码、状态文本与响应头,用来验证依赖状态码的错误渲染。被阻断的请求不会被原生回退重放——否则发出去的正是你要压掉的那个请求。
重试是规则级开关,运行在后台通道。开启后,规则在首次请求之外追加 1 至 5 次尝试,间隔可在 100 至 30000 毫秒之间设置(默认 1000 毫秒)。某次尝试抛出异常(包括触及单请求 30 秒上限被中止)、或返回 5xx 且仍有剩余次数时触发重试;次数用尽后把最后一次响应或错误交回页面。因为重试属于后台通道能力,启用重试的规则永远不会被判定为网络层重定向。
可以。导出为 JSON 配置,默认开启分享模式——自动剔除 Authorization、Cookie 等请求头与响应头、以及 token 类查询参数,需要本机全量备份时取消勾选即可原样导出;同事导入时可选择覆盖,也可与现有规则合并;可把捕获到的流量导出为 HAR 1.2,也可导入别处抓的 HAR 自动生成规则;粘贴一条 cURL 命令(DevTools「复制为 cURL」产物)即可预填规则表单。环境配置快照会保存整套规则的命名副本。规则里的凭据位点写成 {{UAT_TOKEN}} 这样的引用、真值单独存在「设置 → 凭据变量」里之后,导出的配置与环境快照从头到尾没有它,取消分享模式也不会带出去。
最多 200 条规则,最近 500 条请求日志,请求体上限 10 MB,回包正文同样 10 MB
封顶(越界那一笔判失败、不做截断返回;fetch 会按代理失败回退原生再发一次,XHR
不回退、直接以 status 0 报错),延迟 0 至 60000 毫秒,重试默认关闭、开启后追加 1 至 5
次尝试且间隔 100 至 30000 毫秒,单个代理请求 30 秒上限,Mock 与改写的状态码钳制在
200–599,以保证页面总能构造出合法的 Response 对象。
回退行为按通道不同。fetch
在拦截失败或代理失败(超时、超限、后台报错)时回退原生再发一次;XHR
只在同步请求与非字符串请求体这类「代理兑不了」的情况下回退原生,代发本身失败时不会重放,而是把
status 置 0 并派发 error,以免同一个写请求被执行两遍;WebSocket
始终由浏览器原生发出,扩展只改写地址。同步 XHR
与非字符串请求体必须回退,是因为代理要跨上下文往返,兑现不了「send()
返回时结果已就绪」这个契约,异步化只会让页面读到一个空响应。唯一的例外是阻断规则:被阻断的请求绝不会被原生回退重放。
在「试一条规则」面板里点「复制配置 JSON」或「下载 .json」,再打开扩展设置页的「导入/导出配置」,选中这个文件;导入模式选「合并(保留现有,追加新规则)」后确认。合并不会动你现有的规则,也不会替你打开总开关,所以导入后代理还关着的话,去弹窗里打开即可。这份配置里只有一条规则,带匹配类型、匹配模式与目标地址,不含请求头、查询参数或任何凭据。
不能。devServer 的代理按站点内的相对路径(例如
/api)转发,浏览器看到的请求仍然是同源的;要去的后端环境写在 devServer
配置里,从不出现在浏览器实际请求的 URL 上,而扩展的规则按请求 URL
匹配——这份配置里没有一条能对上真实地址,它的字段结构也不是扩展的导入格式。正确做法是按真实 API
来源建一条通配符规则:把 https://fat-api.example.com/* 指向
https://uat-api.example.com,面板里的「用测试地址填匹配模式」可以直接生成这个模式。