Skip to main content

greentic_setup/
http_client.rs

1//! Crate-wide outbound HTTP agent constructors.
2//!
3//! Every outbound call must carry a hard deadline: a stalled remote must
4//! FAIL, never hang the wizard. Bare `ureq::get/post(...)` calls have no
5//! default timeout in ureq 3 — do not add new ones; construct an agent here
6//! instead so the deadline policy stays in one place.
7
8use std::time::Duration;
9
10/// Hard deadline for interactive API calls (OAuth token/device-code
11/// exchanges, Microsoft Graph, provider setup steps). Generous enough for
12/// slow provider backends; small enough that a wedged connection surfaces
13/// as an error while the operator is still watching.
14pub const API_TIMEOUT: Duration = Duration::from_secs(30);
15
16/// Hard deadline for potentially large downloads (bundle archives, tunnel
17/// binaries). Caps the entire transfer, not just connect.
18pub const DOWNLOAD_TIMEOUT: Duration = Duration::from_secs(120);
19
20/// Agent for API calls with ureq's default status handling (non-2xx becomes
21/// `Err(ureq::Error::StatusCode(..))`) — drop-in for bare `ureq::` calls.
22pub fn api_agent() -> ureq::Agent {
23    ureq::Agent::config_builder()
24        .timeout_global(Some(API_TIMEOUT))
25        .build()
26        .new_agent()
27}
28
29/// Agent for API calls where non-2xx statuses are handled as regular
30/// responses (`http_status_as_error(false)`) — drop-in for call sites that
31/// inspect status codes themselves (OAuth polling, Graph error bodies).
32pub fn api_agent_any_status() -> ureq::Agent {
33    ureq::Agent::config_builder()
34        .http_status_as_error(false)
35        .timeout_global(Some(API_TIMEOUT))
36        .build()
37        .new_agent()
38}
39
40/// Agent for downloads: same failure semantics, longer transfer budget.
41pub fn download_agent() -> ureq::Agent {
42    ureq::Agent::config_builder()
43        .timeout_global(Some(DOWNLOAD_TIMEOUT))
44        .build()
45        .new_agent()
46}