Body 重写

Chute 可以使用正则表达式或 JSONPath 表达式在 HTTP 请求和响应正文中搜索并替换内容。对于 HTTPS 流量,这需要启用 MitM 解密。

注意:明文 HTTP 请求只有经由 Chute 的 HTTP 代理到达时才会被处理;经 TUN 接口到达的明文 HTTP 会被原样转发。Chute Android 让所有流量都经过 TUN,除非在设置中打开了系统 HTTP 代理,它会把 Chute 的 HTTP 代理交给应用使用(Android 10 及以上;默认关闭)。

同样支持 Surge 的 http-request-jq 和 http-response-jq 程序——见 Surge 语法。

Body 重写规则定义在 [Body Rewrite] 段中。对于每个方向(请求 / 响应),一条报文只会应用第一条匹配的规则。如果同一条报文还匹配了要读取正文的 http-request 或 http-response 脚本,先应用规则,脚本看到的是改写后的正文;http-request-before-send 脚本在两者之后执行。

[Body Rewrite]
^https://api\.example\.com/response.* response regex "old-text" "new-text"
^https://api\.example\.com/request.* request regex "sensitive" "[redacted]"
^https://api\.example\.com/data.* jsonpath-response jsonpath $.ads null

规则格式

每条规则遵循以下通用格式:

<URL 正则> [方向] <模式> <匹配模式> <替换内容>

注意:URL 正则表达式会在请求完整 URL 的任意位置匹配,也会单独拿路径去匹配(与 URL 重写相同):^https://example\.com 已覆盖该主机下的所有路径和查询字符串,无需在结尾加 .*,^/api 则会匹配路径以 /api 开头的每一个请求。已解密请求的完整 URL 以 https:// 开头,所以 ^http:// 模式永远匹配不到这类请求。模式会保留原本的大小写,因此 \S、\D、\W、\B 的含义不会被改变;匹配本身不区分大小写。

位于行首或紧跟在空格后面的 # 或 // 会开启一段注释,一直到行尾,除非它在双引号之内;; 从不算注释。见注释。

Surge 语法

也接受 Surge 自己的行格式:方向写在最前,省略 regex 关键字。

[Body Rewrite]
http-response ^https://api\.example\.com/feed "\"ads\":\s*\[.*?\]" "\"ads\":[]"
http-request ^https://api\.example\.com/submit "sensitive" "[redacted]"

Surge 形式的行可以写多组「模式 / 替换」,按从左到右的顺序依次应用,每一组作用在前一组的结果上;http-request-jq 与 http-response-jq 用一段 jq 程序代替「模式 / 替换」:<类型> <URL 模式> <jq 程序>,程序通常要加引号,因为里面有空格。在引号之外,紧跟在空格后面的 // 或 # 会开启注释,程序就在那里结束;在引号之内,// 是 jq 的替代运算符,所以用到它的程序要加引号。它把正文当作 JSON 来处理。正文不是 JSON、程序抛出错误、程序没有任何输出——这三种情况都原样保留正文;程序本身无效时会被报告并只跳过这一条规则,不会让整份配置失败。程序读不到文件也读不到环境:import 与 include 解析不到任何东西,$ENV 与 env 都是空的。

注意:Chute Android 用 jackson-jq 运行 jq 程序。它的输出上限为 4096 个结果或 4 MB——产生更多输出的程序会原样保留正文——并且缺少部分 jq 1.7 内置函数,其中包括 now、todateiso8601 和 fromdateiso8601 以外的日期函数(strftime、strptime、mktime、gmtime、todate 等)、@base32 和 @base32d、abs、toarray、trim、ltrim 和 rtrim、IN、INDEX 和 JOIN、tostream 和 fromstream。调用其中任何一个的程序会在运行时抛出错误,正文因此原样保留。

方向

关键字 说明
response 应用于响应正文(省略时的默认值)
request 应用于请求正文

模式

模式 说明
regex 正则表达式搜索替换
jsonpath-response / jsonpath-request / body-jsonpath-response / body-jsonpath-request 基于 JSONPath 的修改

正则模式

对解码后的正文字符串执行标准的正则查找替换。使用 NSRegularExpression (ICU),不区分大小写匹配。替换内容支持捕获组引用($1、$2 等)。

<URL 正则> [response|request] regex <匹配模式> <替换内容>

示例 — 从 JSON 响应中移除广告:

[Body Rewrite]
^https://api\.example\.com/feed.* response regex "\"ads\":\s*\[.*?\]" "\"ads\":[]"

示例 — 清洗请求正文:

[Body Rewrite]
^https://api\.example\.com/submit.* request regex "\"password\":\s*\".*?\"" "\"password\":\"[FILTERED]\""

示例 — 使用捕获组重新格式化数据:

[Body Rewrite]
// 将 "last, first" 转换为 "first last"
^https://api\.example\.com/users.* response regex "\"name\":\s*\"(\w+),\s*(\w+)\"" "\"name\":\"$2 $1\""

示例 — 重写响应正文中的内嵌 URL:

[Body Rewrite]
^https://api\.example\.com.* response regex "https://old-cdn\.example\.com" "https://new-cdn.example.com"

包含空格的词必须用双引号括起来:

[Body Rewrite]
^https://example\.com.* response regex "old value with spaces" "new value"

要在带引号的词里包含字面的双引号,请使用反斜杠转义:\"。


JSONPath 模式

使用 JSONPath 表达式修改 JSON 正文。支持在特定路径读取、设置和删除值。

<URL 正则> jsonpath-response|jsonpath-request jsonpath <jsonpath-表达式> [值]

支持的 JSONPath 语法

表达式 说明
$.key 访问对象属性
$.key.subkey 访问嵌套属性
$[0] 按索引访问数组元素
$.key[0].subkey 混合对象和数组访问
$.items[*].name 通配符:数组中的所有元素
$.*.value 通配符:所有属性

.* 取对象的每一个成员和数组的每一个元素,所以 $.items.*.name 能取到每一项的名字。作为最后一步作用在数组上时,它什么也不改变;要替换元素本身,请用 [*]。

值类型

值 结果
string 设置为字符串值——不属于下面任何一种形式的值都是字符串,所以 example.com、1.0.0-beta、12abc 仍是字符串
42 设置为整数——整个词是一个 JSON 数字,且没有小数部分和指数
3.14 设置为浮点数——带小数部分或指数的 JSON 数字(如 1e3),以及超出 64 位范围的整数
true 设置为布尔值 true
false 设置为布尔值 false
[…] 或 {…} 不加引号时按 JSON 解析,设置为对应的数组或对象;它是最后一个字段,因此这一行余下的内容照原样读取,可以包含空格。加了引号,或者不是合法的 JSON,则仍是字符串。
null、nil 或省略 删除该路径

注意:给值加引号并不会强制其为字符串类型——引号在分词阶段会被剥离,类型根据剩余内容推断,因此 "42" 会变成数字 42,"true" 会变成布尔值 true,"null" 会删除该路径;引号只对 […] 和 {…} 有影响——加了引号,它们仍是字符串。关键字必须完全一致(区分大小写),所以 True 和 NULL 是字符串。只有整个词按 JSON 的写法恰好是一个数字时才算数字:+1、.5、1.、007 仍是字符串,大到连浮点数也表示不了的数(如 1e400)同样是字符串。没有任何写法能设置 "42" 或 "true" 这样的字符串——请改用 regex 规则。

示例 — 设置 JSON 字段:

[Body Rewrite]
^https://api\.example\.com/profile.* jsonpath-response jsonpath $.user.name "Anonymous"

示例 — 删除 JSON 字段:

[Body Rewrite]
^https://api\.example\.com/data.* jsonpath-response jsonpath $.tracking null

示例 — 通配符修改:

[Body Rewrite]
^https://api\.example\.com/list.* jsonpath-response jsonpath $.items[*].hidden true

实践示例

从 JSON 响应中剥离追踪参数

从所有 API 响应中移除 trackingId 字段。由于每个方向只会应用第一条匹配的规则,每个 URL 模式请只使用一条规则:

[Body Rewrite]
^https://api\.example\.com/.* jsonpath-response jsonpath $.trackingId null

向 HTML 响应注入脚本标签

在所有 HTML 页面的 </body> 之前追加自定义 <script> 标签:

[Body Rewrite]
^https://www\.example\.com/.* response regex "</body>" "<script>console.log('injected')</script></body>"

对请求日志中的敏感字段脱敏

在请求正文到达服务器之前替换掉其中的 API 密钥和令牌。由于每个方向只会应用第一条匹配的规则,请将两个字段合并到一条规则中:

[Body Rewrite]
^https://api\.example\.com/.* request regex "\"(apiKey|token)\":\s*\"[^\"]+\"" "\"$1\":\"[REDACTED]\""

规范化响应中的日期格式

将 ISO 日期替换为更短的格式:

[Body Rewrite]
^https://api\.example\.com/.* response regex "(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z" "$1/$2/$3 $4:$5"

禁用应用配置中的功能开关

强制将配置端点中的所有功能开关设为 false:

[Body Rewrite]
^https://api\.example\.com/config.* jsonpath-response jsonpath $.features[*].enabled false

重写缓存响应中的 CDN URL

将对旧 CDN 的所有引用替换为新的 CDN:

[Body Rewrite]
^https://www\.example\.com/.* response regex "https://old-cdn\.example\.com" "https://new-cdn.example.com"

处理管线

Body 重写自动处理以下内容:

  1. Content-Encoding:支持 gzip 和 deflate。跳过不支持的编码。
  2. Transfer-Encoding:在处理前对分块传输编码进行去块化。
  3. 解码:在应用重写规则之前解压缩正文。
  4. 重新编码:重新压缩正文并更新 Content-Length。移除 Transfer-Encoding 头部。
  5. Accept-Encoding:当某条响应规则匹配请求的 URL 时,该请求的 Accept-Encoding 头部会被改写为 gzip, deflate, identity,以确保响应保持在可解码的编码中。

在 HTTP/1.x(明文 HTTP 和解密后的 HTTP/1.1)上,重写处理的正文最大大小为 128KB;更大的正文将直接透传而不做修改。解密后的 HTTP/2 报文会被完整缓冲,无论大小都会被重写。

在 HTTP/1.x 上,响应正文要全部到齐后才会被重写。如果服务器先关闭了连接:既没有 Content-Length 也不是分块编码的正文以连接关闭为结尾,此时已经完整,照常重写;按 Content-Length 或分块编码分帧、却被关闭截断的正文按收到的原样发给客户端,不做重写,Content-Length 也不改,随后关闭连接,让客户端能察觉响应不完整。


注意事项

  • 对于 HTTPS 流量,必须为匹配的主机名启用 MitM 解密。
  • 正则匹配不区分大小写。替换模板支持 ICU 捕获组引用:$0(完整匹配)、$1(第一组)、$2(第二组)等。
  • URL 模式或正文的匹配模式不是有效的正则表达式时,正则或 JSONPath 行会成为配置错误,该规则不会被加载;jq 行则会被跳过并给出警告。在第一组之后的各组「模式 / 替换」中,无效的模式只会丢弃那一组,并在日志中给出警告。
  • JSONPath 模式仅在正文是有效 JSON 时适用。
  • Body 重写规则应用于解码后(UTF-8)的正文文本。
  • 每个方向(请求 / 响应)上,一条报文只会应用第一条匹配的规则。如果需要多处修改,请定义一条合并的规则。
  • 删除不存在的 JSONPath 时正文保持不变。设置值时,如果其父对象存在则会创建该键;如果中间路径缺失,则不会有任何变化。
S. Smart Rabbit LLC © All Rights Reserved            updated 2026-09-29 21:57:05

本页为英文版的翻译。如内容有出入,以英文版为准。

results matching ""

    No results matching ""