better_fetch/backend/
mod.rs1pub(crate) mod exec;
10mod reqwest;
11
12pub use reqwest::ReqwestBackend;
13
14use async_trait::async_trait;
15use bytes::Bytes;
16use http::{HeaderMap, Method, StatusCode};
17use std::time::Duration;
18
19use crate::cancel::CancellationToken;
20use crate::streaming::BodyStream;
21use crate::Result;
22
23#[cfg(feature = "multipart")]
24use crate::multipart::Form as MultipartForm;
25
26#[derive(Debug, Clone, Default)]
28pub enum HttpBody {
29 #[default]
31 Empty,
32 Bytes(Bytes),
34}
35
36#[derive(Debug)]
38pub struct HttpRequest {
39 pub method: Method,
41 pub url: url::Url,
43 pub headers: HeaderMap,
45 pub body: HttpBody,
47 pub timeout: Option<Duration>,
49 pub cancellation: Option<CancellationToken>,
51 #[cfg(feature = "multipart")]
52 pub multipart: Option<MultipartForm>,
54}
55
56impl Clone for HttpRequest {
57 fn clone(&self) -> Self {
58 Self {
59 method: self.method.clone(),
60 url: self.url.clone(),
61 headers: self.headers.clone(),
62 body: self.body.clone(),
63 timeout: self.timeout,
64 cancellation: self.cancellation.clone(),
65 #[cfg(feature = "multipart")]
66 multipart: None,
67 }
68 }
69}
70
71#[derive(Debug, Clone)]
73pub struct HttpResponse {
74 pub status: StatusCode,
76 pub headers: HeaderMap,
78 pub body: Bytes,
80}
81
82pub struct HttpStreamingResponse {
84 pub status: StatusCode,
86 pub headers: HeaderMap,
88 pub body: BodyStream,
90}
91
92impl std::fmt::Debug for HttpStreamingResponse {
93 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94 f.debug_struct("HttpStreamingResponse")
95 .field("status", &self.status)
96 .field("headers", &self.headers)
97 .field("body", &"<stream>")
98 .finish()
99 }
100}
101
102#[async_trait]
104pub trait HttpBackend: Send + Sync {
105 async fn execute(&self, request: HttpRequest) -> Result<HttpResponse>;
107
108 async fn execute_stream(&self, request: HttpRequest) -> Result<HttpStreamingResponse>;
110}