Skip to main content

better_fetch/
lib.rs

1//! # better-fetch
2//!
3//! Typed HTTP client layer on top of [reqwest](https://docs.rs/reqwest), inspired by
4//! [@better-fetch/fetch](https://better-fetch.vercel.app/docs). This crate is not affiliated
5//! with the upstream TypeScript project.
6//!
7//! ## Quick flow
8//!
9//! 1. Create a [`Client`] (or [`ClientBuilder`]) with a base URL.
10//! 2. Start a request with [`Client::get`] / [`Client::post`] / [`Client::call`].
11//! 3. Configure path params, query, body, auth, retries on [`RequestBuilder`].
12//! 4. Execute with [`RequestBuilder::send`] (returns [`Response`]) or [`RequestBuilder::send_json`]
13//!    (deserializes JSON and fails on non-2xx).
14//!
15//! ## Cargo features
16//!
17//! | Feature | Description |
18//! |---------|-------------|
19//! | `json` (default) | JSON bodies, `send_json`, custom [`JsonParserFn`] |
20//! | `reqwest` / `rustls-tls` (default) | Reqwest backend |
21//! | `multipart` | [`RequestBuilder::multipart`] |
22//! | `tower` | Tower transport stack via [`ClientBuilder::transport_stack`] |
23//! | `schema` | [`SchemaRegistry`] route metadata |
24//! | `openapi` | OpenAPI 3.0 export from schema registry |
25//! | `validate` | Garde validation on JSON responses |
26//! | `macros` | Proc-macro helpers (reserved) |
27//!
28//! See the [repository README](https://github.com/sebasxsala/better-fetch-rs) for full examples.
29//!
30//! ## Example
31//!
32//! ```no_run
33//! # use better_fetch::{Client, Result};
34//! # use serde::Deserialize;
35//! # #[derive(Debug, Deserialize)]
36//! # #[serde(rename_all = "camelCase")]
37//! # struct Todo { user_id: u64, id: u64, title: String, completed: bool }
38//! # #[tokio::main]
39//! # async fn main() -> Result<()> {
40//! let client = Client::new("https://jsonplaceholder.typicode.com")?;
41//!
42//! // send() returns Response for any status; json() fails on non-2xx
43//! let todo: Todo = client
44//!     .get("/todos/:id")
45//!     .param("id", 1)
46//!     .send()
47//!     .await?
48//!     .json()
49//!     .await?;
50//!
51//! // Or in one step:
52//! let todo: Todo = client.get("/todos/:id").param("id", 1).send_json().await?;
53//! # Ok(())
54//! # }
55//! ```
56
57mod url_build;
58
59pub mod auth;
60pub mod backend;
61pub mod cancel;
62pub mod client;
63pub mod endpoint;
64pub mod error;
65pub mod hooks;
66#[cfg(feature = "json")]
67mod json_parser;
68
69pub mod plugin;
70pub mod plugins;
71pub mod request;
72pub mod response;
73pub mod retry;
74#[cfg(feature = "validate")]
75mod validate_json;
76
77#[cfg(feature = "schema")]
78pub mod schema;
79
80#[cfg(feature = "openapi")]
81pub mod openapi;
82
83#[cfg(feature = "tower")]
84pub mod tower;
85
86pub use auth::{AsyncTokenProvider, Auth, TokenSource};
87pub use backend::{HttpBackend, HttpBody, HttpRequest, HttpResponse, ReqwestBackend};
88pub use cancel::CancellationToken;
89#[cfg(feature = "multipart")]
90/// Re-export of [reqwest multipart](https://docs.rs/reqwest/latest/reqwest/multipart/) types (feature `multipart`).
91pub use reqwest::multipart;
92pub use client::{Client, ClientBuilder, ClientConfig};
93pub use endpoint::{Endpoint, EndpointParams, EndpointQuery, EndpointRequestBuilder};
94pub use error::Error;
95pub use hooks::{ErrorContext, Hooks, RequestContext, ResponseContext, SuccessContext};
96#[cfg(feature = "json")]
97pub use json_parser::{json_parser, serde_json_parser, JsonParserFn};
98pub use plugin::{Plugin, PluginRegistry, PreparedRequest};
99pub use plugins::LoggerPlugin;
100pub use request::RequestBuilder;
101pub use response::Response;
102pub use retry::{default_should_retry, parse_retry_after, RetryPolicy, ShouldRetryFn};
103pub use url_build::QueryValue;
104
105#[cfg(feature = "schema")]
106pub use schema::{EndpointSchema, SchemaRegistry};
107
108#[cfg(feature = "openapi")]
109pub use openapi::{
110    OpenApiBuilder, OpenApiComponents, OpenApiDocument, OpenApiInfo, OpenApiOperation, OpenApiSchemaRef,
111    OpenApiServer,
112};
113
114#[cfg(feature = "tower")]
115pub use tower::{BoxHttpService, ReqwestHttpService, ServiceBackend};
116
117/// Result alias using [`Error`].
118pub type Result<T> = std::result::Result<T, Error>;