feat(download): 把 download.proxy_mode / download.proxy_url 接进代理三态(M295)
台账 P26:两个键引擎侧零消费者——`http::build_client` 只设 UA / 连接超时 / 重定向 / 默认头, 从不 `.proxy()`。设置页画着三档 chip 与一个地址框,改它对任何一次下载都不生效(`system` 那一 档「碰巧能用」只是因为 reqwest 默认读环境变量,不是这段代码做的)。 - core::download::proxy(新):`ProxySetting::from_raw` 是**唯一**翻译层,三档落到 client 上: `none` ⇒ `.no_proxy()`(真直连,连 `HTTP_PROXY` 也不读)/ `system` ⇒ 不调任何代理 API (跟随环境变量 = M295 之前的行为)/ `manual` ⇒ `.proxy(Proxy::all(url))`;未知值 ⇒ `none`。 - 两条决定写进模块头:`proxy_url` 在非 manual 档**忽略**(不校验、不进结构,值原样留在文件 里);`manual` + 空地址 ⇒ `system`(设置页那行文案一直这么承诺)。 - 非法地址不穿透:`Proxy::all` 解析失败 ⇒ 有界错误(`InvalidRequest` + 带原串的文案),不 panic;`DownloadEngine::new` 回落**直连**重建(不用 `reqwest::Client::new()`——那会跟随环境 变量代理,回落就不确定),原因留在 `proxy_problem()`,CLI 的 `download::engine` 打一行 stderr;`config().proxy` 不撒谎(仍是用户写的 `manual`)。 - `EngineConfig.proxy` 默认 `System`(=「没读设置」的档:auth 登录 / JDK 下载页 / 地区探测都 直接用它,保持老行为),`DownloadTuning.proxy` 默认 `Direct`(与 schema 的 `none` 一致)。 - 两键进 `RawTuning`(与 `gh_proxy` 同形),presenter 的 `tuning_of` 与 CLI 的 `tuning` 各加 两行;两个宿主都是完整字段字面量 ⇒ 「忘了读」是编译错误。`summary()` 加 `代理=…` 一档。 - 判据是「请求真的经过代理」:新夹具 `FakeProxy`(本地 TcpListener)+ 目标 `.invalid`(解析不 了)⇒ 拿到正文只可能来自代理,且代理记到的请求行是**绝对 URI**。三条用例:manual 真走代理 / direct 无视环境变量而 system 跟随(同一份 `HTTP_PROXY`)/ 非法地址回落直连不 panic。 变异 M17-M22 记在 docs/download-settings.md §6。 - 行为变化(doc §5.2 写明):`none` 从「碰巧跟随环境变量」变成真直连,靠 `HTTP_PROXY` 上网的 用户要选一次 `system`。发布版 GUI 的「下载 JDK」页仍不读这两个键(finding 已开)。 - 门禁:四 crate `check --all-targets` / 测试(3201 passed, 0 failed)/ `clippy -D warnings` / `fmt --check`;另跑了 `check --workspace --all-targets`。判据用 `$?` 与 `test result:` 行验。
This commit is contained in:
1 parent
c731d3fa54
commit
d584a2c42e
16 files changed
+1000
-56
No files matched your search
@@ -40,25 +40,29 @@ pub const USER_AGENT: &str = concat!(
|
||||
" (+https://github.com/AskaEth/Unlucky-Launcher)"
|
||||
);
|
||||
|
||||
/// 构造共享的 `reqwest::Client`(连接池、超时、重定向策略一次定好)。
|
||||
/// 构造共享的 `reqwest::Client`(连接池、超时、重定向策略、代理一次定好)。
|
||||
///
|
||||
/// **代理由配置决定,不在这里解释字符串**:`cfg.proxy` 是 `download.proxy_mode` / `proxy_url` 的
|
||||
/// 翻译结论(唯一翻译层是 [`super::proxy`]),三档各自落到 `.no_proxy()` / 什么都不做 /
|
||||
/// `.proxy(Proxy::all(url))`。地址解析不了时返回**有界错误**(不 panic)——装配点
|
||||
/// (`DownloadEngine::new`)据此回落直连并把原因留在引擎上,见 [`super::proxy`] 模块头。
|
||||
pub fn build_client(cfg: &EngineConfig) -> Result<reqwest::Client, DownloadError> {
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(
|
||||
ACCEPT_ENCODING,
|
||||
reqwest::header::HeaderValue::from_static("identity"),
|
||||
);
|
||||
reqwest::Client::builder()
|
||||
let builder = reqwest::Client::builder()
|
||||
.user_agent(cfg.user_agent.clone())
|
||||
.connect_timeout(cfg.connect_timeout)
|
||||
.redirect(Policy::limited(MAX_REDIRECTS))
|
||||
.default_headers(headers)
|
||||
.build()
|
||||
.map_err(|err| {
|
||||
DownloadError::new(
|
||||
DownloadErrorKind::Network,
|
||||
format!("构造 HTTP 客户端失败:{err}"),
|
||||
)
|
||||
})
|
||||
.default_headers(headers);
|
||||
cfg.proxy.apply(builder)?.build().map_err(|err| {
|
||||
DownloadError::new(
|
||||
DownloadErrorKind::Network,
|
||||
format!("构造 HTTP 客户端失败:{err}"),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// **每一条 `send()` 的唯一上界构造点**:`transfer.rs` 的单连接请求、`chunked.rs` 的分块请求、
|
||||
|
||||
Reference in new issue
Block a user