1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//! One source for captchaforge's plain (non-impersonating) HTTP clients.
//!
//! The CAPTCHA backends/solvers each talk to a *local* service (Ollama,
//! Whisper, Tesseract sidecar) or a vendor solver API, not to the target
//! site, so they want a plain timed client, not the browser-impersonating
//! [`guise`] client. The same `reqwest::Client::builder().timeout(d).build()`
//! block was copy-pasted across `backends`, `solver::{audio,third_party,
//! vlm}`, `stt`, and the CLI. Centralizing it here gives one place to evolve
//! connection policy (connect-timeout, pooling, a default UA) for all of them.
use Duration;
/// A plain reqwest client with a total-request `timeout` and no browser
/// impersonation. Callers that can return an error own their own handling
/// (`?`, `match`, `.ok()?`). Callers in an *infallible* constructor must use
/// [`timed_client_or_panic`]. NOT `.unwrap_or_else(|_| reqwest::Client::new())`.
pub
/// [`timed_client`] for the handful of infallible solver constructors that
/// cannot return a `Result`.
///
/// Law 10: the historical `.unwrap_or_else(|_| reqwest::Client::new())` at these
/// sites was a SILENT fallback *and* a footgun, it dropped the caller's
/// `timeout` (returning an un-timed client that can hang a solve forever), and
/// `reqwest::Client::new()` itself panics on the very same build failure, just
/// with a less useful message. A reqwest client only fails to build when the TLS
/// backend can't initialise: a fatal environment problem, not something to paper
/// over with a differently-configured client. So fail LOUD, with the cause and
/// the fix, and never hand back a client whose timeout was silently discarded.
pub