Skip to content

fix: resReplace 含 & 时, 误发 HTTP 请求导致卡顿 - #1322

Open
alsotang wants to merge 1 commit into
avwo:masterfrom
alsotang:master
Open

alsotang wants to merge 1 commit into
avwo:masterfrom
alsotang:master

Conversation

@alsotang

@alsotang alsotang commented Apr 9, 2026

Copy link
Copy Markdown

---- 人话 ----
我这段时间在做一个基于vscode web版本的项目,dev模式下,每次都要加载7000+个文件。对应的 whistle 规则里面,我用了

gamemaker.weixin.qq.com resReplace://http://gamemaker.weixin.qq.com=https://gamemaker.weixin.qq.com&http://{{uuid}}.gamemaker.weixin.qq.com=https://{{uuid}}.gamemaker.weixin.qq.com

这样一句。一开始也没觉得有什么不对。直到今早上,帮别人排查一个sse的问题(其实在这个bug场景中,sse是个干扰项),结果对应的response总是迟到20+s才返回,我就拉着后台和运维同事和测试组的同事折腾了一早上。结果他们发现,用shell的curl来重现问题,就无法重现,只有我的浏览器有问题。

我百思不得其解,不甘心查了一下午,发现原来是whistle的这个 resReplace 的解析方式有问题。

---- ai commit message ----
getMatcherJson 遇到值中 = 后有 & 会跳过解析,导致 readRuleValue
将 http:// 开头的 matcher 当作 URL 发起请求,超时约 16s。
在 readRuleValue 之前增加 tryParseMatcher fallback 即可避免。

---- ai pr message ----

这是我跟cursor用debug mode查了一下午,总结历史而成的pr message。我自测这个fix是没问题的,但是否修在了精准的地方,还得您来判断。

## **resReplace 含 `&` 分隔多组替换时,响应卡顿 15-30 秒**

### **问题**

使用 `resReplace` 配置多组替换(用 `&` 分隔 key=value 对)时,例如:

pattern resReplace://http://a.com=https://a.com&http://b.com=https/://b.com

每个匹配到的响应都会卡顿约 16-32 秒。在大量文件并发加载的场景(如 VS Code Web 初始化 7000+ 文件)下,页面几乎不可用。

### **原因**

`readRuleList` 解析规则值时依次调用 `getMatcherJson` → `parsePureJSON`,均失败后 fallback 到 `readRuleValue`- `getMatcherJson`:发现 `=` 后面存在 `&`,误判为 query string 格式,直接 return
- `parsePureJSON`:值不是合法 JSON,解析失败
- `readRuleValue` → `resolveKey`:值以 `http://` 开头,被当作远程 URL 发起 HTTP 请求
- 目标路径无效(如 `http://a.com/=https://a.com&...`),等待 16 秒超时后自动重试,合计约 32 秒

超时返回空值后,`tryParseMatcher` 作为 post-hoc fallback 用 `parseQuery` 成功解析——**替换功能正常,但白白等了一个超时周期**### **修复**

在 `readRuleValue` 之前增加 `tryParseMatcher(null, rule)` 作为第三级 fallback。该函数用 `parseQuery` 按 `&` 分割 key=value,本身已作为 `readRuleValue` 返回后的兜底逻辑存在,只是调用时机太晚。提前到 inline 解析阶段即可避免无意义的 HTTP 请求。

getMatcherJson 遇到值中 = 后有 & 会跳过解析,导致 readRuleValue
将 http:// 开头的 matcher 当作 URL 发起请求,超时约 16s。
在 readRuleValue 之前增加 tryParseMatcher fallback 即可避免。
@alsotang

alsotang commented Apr 9, 2026

Copy link
Copy Markdown
Author
gamemaker.weixin.qq.com resReplace://http://gamemaker.weixin.qq.com=https://gamemaker.weixin.qq.com&http://{{uuid}}.gamemaker.weixin.qq.com=https://{{uuid}}.gamemaker.weixin.qq.com

我这个写法看着就很怪。其实这种复杂的替换,我应该一开始就用正则才对的。
感觉也不一定要merge这个pr。close也行。

@avwo

avwo commented Apr 9, 2026

Copy link
Copy Markdown
Owner

你配置的规则存在一点问题。resReplace 支持从以下几种方式加载操作内容:

# 本地文件
resReplace:///Usr/xxx/xxx

# 远程 URL
resReplace://http(s)://xxx

# Values / 内嵌值
resReplace://{xxx.json}

# 内联值(需用小括号括起来)
resReplace://(xxxx&xxxx或不含空格的JSON字符串)

# 包含 = 但不是 url 及 本地文件
resReplace://k1=v1&k2=v2

而你实际配置的是:

gamemaker.weixin.qq.com resReplace://http://gamemaker.weixin.qq.com=https://gamemaker.weixin.qq.com&http://{{uuid}}.gamemaker.weixin.qq.com=https://{{uuid}}.gamemaker.weixin.qq.com

Whistle 会将 http://gamemaker.weixin.qq.com=https://gamemaker.weixin.qq.com&http://{{uuid}}.gamemaker.weixin.qq.com=https://{{uuid}}.gamemaker.weixin.qq.com 误识别为加载操作内容的 URL,而非内联值。解决方法是在内容外加小括号,将其明确指定为内联值:

gamemaker.weixin.qq.com resReplace://(http://gamemaker.weixin.qq.com=https://gamemaker.weixin.qq.com&http://{{uuid}}.gamemaker.weixin.qq.com=https://{{uuid}}.gamemaker.weixin.qq.com)

为避免此类问题,务必使用小括号将其包裹为内联值。我看下能不能避免这类情况。

@alsotang

alsotang commented Apr 9, 2026

Copy link
Copy Markdown
Author
  1. 我觉得自己的用法是存在问题的,我写了 http:// 在里面,这种情况我应该直接转向正则就好了。不过whistle如果能提醒一下最好。我是后知后觉。
  2. 之所以后知后觉,是因为它真的能跑,能通。虽然有个16s的初始延迟,但我总以为是vite那边编译的耗时,所以一开始没在意。
  3. 虽然能跑,但走的是fallback逻辑跑起来的。

这些因素纠缠在一起,所以我个人感觉还是不要merge这个pr了吧。就当我是反馈一下问题。

@alsotang

alsotang commented Apr 9, 2026

Copy link
Copy Markdown
Author

我个人看来,最简单的方式是,whistle在这种value隔离不明确的场景,可以尝试检测一下特殊字符,然后无论通不通(静态检测,无法确定),都提示用户,这种用法可能导致进入不可知的场景。引导用户采用正则这样更确定性的路径。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants