From f9de5205ae5ac3b9acb921562db580268627c816 Mon Sep 17 00:00:00 2001 From: angela-helios Date: Thu, 30 Jul 2026 22:42:09 -0400 Subject: [PATCH] fix(terminology): the HTS client must fail fast, not hang behind a proxy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test_in_modifier_fails_open_on_hts_unavailable points :in at a closed local port and expects fail-open within the 10s request timeout. On pool runners whose no_proxy excludes private ranges via CIDR — which reqwest cannot parse — the request detoured through the egress proxy and hung for minutes (789s in PR #466's run) before surfacing as a 500. The terminology server is a configured internal endpoint: the client now bypasses proxies outright, adds a 2s connect timeout so an unreachable server fails in milliseconds, and drops the silent unwrap_or_default() fallback that could discard both timeouts when the builder errs. --- crates/rest/src/terminology.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/crates/rest/src/terminology.rs b/crates/rest/src/terminology.rs index 58033bf0b..d6fe6eb62 100644 --- a/crates/rest/src/terminology.rs +++ b/crates/rest/src/terminology.rs @@ -87,12 +87,24 @@ impl TerminologyServiceClient { /// Creates a new client targeting the given base URL. /// /// Trailing slashes in `base_url` are trimmed automatically. - /// A 10-second timeout is applied to all requests. + /// A 10-second timeout is applied to all requests, with a short connect + /// timeout so an unreachable server fails fast — the `:in` fail-open + /// semantics depend on it. + /// + /// The client bypasses any proxy environment: the terminology server is a + /// configured internal endpoint, and routing it through an egress proxy + /// turns "connection refused in milliseconds" into a multi-minute hang on + /// runners whose `no_proxy` uses CIDR ranges reqwest cannot parse. The + /// previous silent `unwrap_or_default()` fallback could also discard the + /// timeouts entirely; a client build failure is a startup-visible + /// misconfiguration, not something to paper over. pub fn new(base_url: String) -> Self { let client = Client::builder() .timeout(Duration::from_secs(10)) + .connect_timeout(Duration::from_secs(2)) + .no_proxy() .build() - .unwrap_or_default(); + .expect("terminology HTTP client"); Self { client,