Skip to main content

better_fetch/backend/
mod.rs

1//! HTTP transport abstraction.
2//!
3//! The default backend is [`ReqwestBackend`]. Inject a custom [`HttpBackend`] via
4//! [`ClientBuilder::backend`](crate::ClientBuilder::backend) for tests or alternate transports.
5
6pub(crate) mod exec;
7mod reqwest;
8
9pub use reqwest::ReqwestBackend;
10
11use async_trait::async_trait;
12use bytes::Bytes;
13use http::{HeaderMap, Method, StatusCode};
14use std::time::Duration;
15
16use crate::cancel::CancellationToken;
17use crate::Result;
18
19#[cfg(feature = "multipart")]
20use crate::multipart::Form as MultipartForm;
21
22/// Request body encoding for the transport layer.
23#[derive(Debug, Clone, Default)]
24pub enum HttpBody {
25    /// No body.
26    #[default]
27    Empty,
28    /// Raw bytes body.
29    Bytes(Bytes),
30}
31
32/// Prepared HTTP request passed to a backend.
33#[derive(Debug)]
34pub struct HttpRequest {
35    /// HTTP method.
36    pub method: Method,
37    /// Fully resolved URL.
38    pub url: url::Url,
39    /// Request headers.
40    pub headers: HeaderMap,
41    /// Body when not using multipart.
42    pub body: HttpBody,
43    /// Per-request timeout.
44    pub timeout: Option<Duration>,
45    /// Cooperative cancellation.
46    pub cancellation: Option<CancellationToken>,
47    #[cfg(feature = "multipart")]
48    /// Multipart form (feature `multipart`).
49    pub multipart: Option<MultipartForm>,
50}
51
52impl Clone for HttpRequest {
53    fn clone(&self) -> Self {
54        Self {
55            method: self.method.clone(),
56            url: self.url.clone(),
57            headers: self.headers.clone(),
58            body: self.body.clone(),
59            timeout: self.timeout,
60            cancellation: self.cancellation.clone(),
61            #[cfg(feature = "multipart")]
62            multipart: None,
63        }
64    }
65}
66
67/// Raw HTTP response from a backend.
68#[derive(Debug, Clone)]
69pub struct HttpResponse {
70    /// HTTP status.
71    pub status: StatusCode,
72    /// Response headers.
73    pub headers: HeaderMap,
74    /// Response body bytes.
75    pub body: Bytes,
76}
77
78/// Pluggable HTTP transport used by [`Client`](crate::Client).
79#[async_trait]
80pub trait HttpBackend: Send + Sync {
81    /// Executes one HTTP request and returns the raw response.
82    async fn execute(&self, request: HttpRequest) -> Result<HttpResponse>;
83}