tt_provider_gemini/client.rs
1//! HTTP client configuration for the Gemini adapter.
2//!
3//! The client has a connection timeout but intentionally does **not** configure
4//! retries — that responsibility belongs to the `tt-core` retry/backoff layer.
5//! Adapters are retry-unaware by design.
6
7use std::time::Duration;
8
9use reqwest::Client;
10
11/// Configuration supplied to [`build_client`].
12#[derive(Debug, Clone)]
13pub struct ClientConfig {
14 /// Per-read idle timeout: resets on each received chunk, so a long
15 /// streaming response is not cut off, while a stalled connection still
16 /// times out. (Not a total-request cap.) Defaults to 120 s.
17 pub timeout: Duration,
18 /// TCP connection timeout. Defaults to 10 s.
19 pub connect_timeout: Duration,
20}
21
22impl Default for ClientConfig {
23 fn default() -> Self {
24 Self {
25 timeout: Duration::from_secs(120),
26 connect_timeout: Duration::from_secs(10),
27 }
28 }
29}
30
31/// Build a [`reqwest::Client`] with the given configuration.
32///
33/// Uses rustls (no native TLS) and enables gzip decompression. The client is
34/// intended to be created once per [`crate::GeminiProvider`] and reused
35/// across all requests.
36pub fn build_client(cfg: &ClientConfig) -> Result<Client, reqwest::Error> {
37 Client::builder()
38 .read_timeout(cfg.timeout)
39 .connect_timeout(cfg.connect_timeout)
40 // Disable automatic redirects — the provider API should not redirect.
41 .redirect(reqwest::redirect::Policy::none())
42 // Use rustls (consistent with workspace default features).
43 .use_rustls_tls()
44 .gzip(true)
45 .build()
46}