如何通过Fiddler强制同一域名的所有请求复用单个ServerPipe
需求可行性结论
该需求可以实现,你当前的核心问题是:手动通过x-ReplyWithTunnel创建的隧道会话没有绑定到已有的有效ServerPipe,Fiddler默认不会自动将不同ClientPipe的请求路由到同一个已存在的服务端连接上,因此后续5个隧道过来的GET请求找不到对应的服务端出口,自然无响应。
遗漏的配置与逻辑补充
1. 全局缓存有效ServerPipe实例
首先需要在FiddlerScript中定义全局变量,存储目标域名对应的已建联ServerPipe:
// FiddlerScript 全局变量定义区添加 static var g_TargetDomain = "example.com:443"; // 替换为你的目标域名+端口 static var g_SharedServerPipe: PipeServer = null;
在第一个CONNECT请求的OnPeekAtResponseHeaders阶段(此时服务端连接已建联成功),缓存ServerPipe实例:
if (oSession.HTTPMethodIs("CONNECT") && oSession.Host == g_TargetDomain && g_SharedServerPipe == null) { // 等待连接建联成功后缓存 oSession.OnStateChanged += (s) => { if (s == SessionStates.SendingResponse) { g_SharedServerPipe = oSession.oRequest.pipeServer; } }; // 同时强制该域名的服务端连接池上限为1,避免底层自动新建连接 oSession["x-ConnectionPoolLimit"] = "1"; }
注意增加失效逻辑:每次使用缓存前判断g_SharedServerPipe != null && g_SharedServerPipe.IsConnected,如果连接已断开则清空缓存,触发重新建联。
2. 后续CONNECT请求的标识标记
你当前给后续CONNECT设置x-ReplyWithTunnel的逻辑不变,额外给该会话增加自定义标记,标识该隧道下的所有请求需要复用共享ServerPipe:
if (oSession.HTTPMethodIs("CONNECT") && oSession.Host == g_TargetDomain && g_SharedServerPipe != null && g_SharedServerPipe.IsConnected) { oSession["x-ReplyWithTunnel"] = "manual-tunnel"; oSession["UseSharedServerPipe"] = "true"; // 新增自定义标记 }
3. 普通请求的ServerPipe绑定
在OnBeforeRequest阶段,检测当前请求所属的隧道是否带有复用标记,手动绑定到缓存的共享ServerPipe:
if (oSession.oRequest.pipeClient != null && oSession.oRequest.pipeClient.AssociatedTunnel != null && oSession.oRequest.pipeClient.AssociatedTunnel["UseSharedServerPipe"] == "true" && g_SharedServerPipe != null && g_SharedServerPipe.IsConnected) { // 手动绑定服务端连接 oSession.oRequest.pipeServer = g_SharedServerPipe; // 禁止Fiddler新建服务端连接 oSession["x-NoNewConnection"] = "true"; // 增加连接复用计数,避免Fiddler主动关闭共享连接 g_SharedServerPipe.ReuseCount++; }
4. 基础配置检查
打开Fiddler的Tools > Options > Connections,确认Reuse connections to servers选项已勾选,该选项是Fiddler支持服务端连接复用的基础开关。
优化方案(无需手写逻辑)
如果目标域名支持HTTP/2,直接开启Fiddler的Tools > Options > HTTPS > Enable HTTP/2 support即可,HTTP/2本身会对同一域名的所有请求复用单个TCP连接,Fiddler会自动只创建1个ServerPipe,不需要手动编写上述逻辑。
内容的提问来源于stack exchange,提问作者OrdinaryOrange

