Skip to main content

rainier_http_client/
lib.rs

1//! # rainier-http-client
2//!
3//! Calling somebody else's HTTP API, and — more importantly — asserting that
4//! you did.
5//!
6//! ```ignore
7//! let response = Http::post("https://hooks.example.com/user-updated")
8//!     .json(&payload)?
9//!     .timeout(Duration::from_secs(10))
10//!     .retry(3, Backoff::exponential())
11//!     .send()
12//!     .await?;
13//!
14//! response.error_for_status()?;
15//! ```
16//!
17//! Without a framework-supplied client, every
18//! application that calls out — a webhook, an OAuth token exchange, a
19//! geolocation lookup — builds its own, with its own timeout and its own
20//! idea of what to retry.
21//!
22//! # The fake is the point
23//!
24//! ```ignore
25//! Http::fake();                       // record instead of sending
26//!
27//! notify_application(&user).await?;
28//!
29//! Http::assert_sent(|request| {
30//!     request.url().ends_with("/hooks/user-updated")
31//!         && request.header("x-signature").is_some()
32//! });
33//! ```
34//!
35//! Without one, asserting that an outbound call happened means standing up a
36//! real server in a test — so nobody does, and the code that signs the webhook
37//! is the code nothing exercises. That is not hypothetical: it is how a
38//! webhook signing bug survives a port.
39//!
40//! `Http::fake()` also **refuses to reach the network**, which is the other
41//! half. A suite that accidentally calls a real endpoint is a suite that fails
42//! when somebody runs it on a train.
43//!
44//! # What it deliberately does not do
45//!
46//! No connection pooling knobs, no proxy configuration, no cookie jar, no
47//! streaming upload. `ReqwestTransport::with_client` takes a client you
48//! configured for anything this does not cover — the point of this crate is
49//! the ergonomics and the fake, not hiding a good library.
50//!
51//! # The transport is opt-in
52//!
53//! `reqwest-transport` is **not** a default feature. It brings a TLS stack, an
54//! HTTP/2 implementation and an IDNA table, and a build that only needs the
55//! client API and the fake — a test suite, a Worker, a crate that takes a
56//! [`Transport`] as an argument — should not pay for any of it. Without it,
57//! `send()` reports that nothing is installed rather than silently doing
58//! nothing.
59//!
60//! The framework turns it on through its own `http-client` feature.
61
62#![deny(missing_docs)]
63#![deny(rustdoc::broken_intra_doc_links)]
64
65pub mod fake;
66pub mod request;
67pub mod response;
68pub mod retry;
69pub mod transport;
70
71pub use fake::{FakeTransport, RecordedRequest};
72pub use request::{Http, PendingRequest};
73pub use response::HttpResponse;
74pub use retry::Backoff;
75pub use transport::Transport;
76
77#[cfg(feature = "reqwest-transport")]
78pub use transport::ReqwestTransport;