如何让reqwest::Client所有请求始终通过代理并复用代理连接?
解决reqwest Client复用连接时跳过代理的问题
要让所有请求始终通过代理,同时复用与代理的连接,你可以从以下几个方面排查和解决:
1. 确保代理配置全局生效
检查你的Client构建代码,使用Proxy::all()而非单独的http/https方法设置代理,确保覆盖所有请求类型:
use reqwest::{Client, Proxy}; use anyhow::Result; fn build_proxied_client() -> Result<Client> { let proxy = Proxy::all("http://10.12.128.5:3128")?; let client = Client::builder() .proxy(proxy) // 可选:开启连接日志,确认连接目标 .connection_verbose(true) .build()?; Ok(client) }
克隆后的Client会完全继承原实例的代理配置,无需额外设置。
2. 排除环境变量干扰
检查系统环境变量NO_PROXY/no_proxy,确认没有将目标地址test.local加入跳过代理的列表。如果存在该配置,reqwest会自动绕过代理直接连接目标。
3. 验证代理日志的准确性
你看到的“仅三分之一请求经过代理”可能是代理日志的误导:
- 当通过HTTP代理访问HTTPS目标时,客户端会先发送
CONNECT请求与代理建立隧道,后续所有同目标的请求都会通过该隧道传输。 - 多数代理(如Squid)默认仅记录
CONNECT请求,不会记录隧道内加密的HTTPS请求内容,导致你误以为后续请求没走代理。 - 调整代理日志配置,使其记录所有通过代理的流量(若代理支持HTTPS解密,可记录请求详情;否则至少记录隧道的持续连接)。
4. 排查连接池复用逻辑
reqwest基于hyper的连接池,默认按(协议, 目标主机, 端口)缓存连接。当使用代理时,实际TCP连接是与代理建立的,缓存的key是目标地址,但复用的仍是通过代理的隧道连接。如果仍有请求直接连接目标:
- 升级reqwest到最新稳定版,避免旧版本的代理逻辑bug。
- 检查测试代码中是否存在请求级别覆盖代理的操作(如调用
.no_proxy())。
如果确实需要让连接池直接以代理地址为缓存key(适用于多目标场景复用代理连接),则需要自定义hyper的连接池逻辑,但这需要深入底层开发,一般场景下无需这么做。
内容的提问来源于stack exchange,提问作者dakami
相关产品推荐
相关产品推荐

