monoio_http_client/
request.rs

1use bytes::Bytes;
2use http::{header::HeaderName, request::Builder, HeaderValue, Method, Uri};
3use monoio_http::common::body::{FixedBody, HttpBody};
4
5use crate::{
6    client::{
7        connector::PooledConnector, key::Key, pool::PooledConnection,
8        unified::UnifiedTransportConnector, Client,
9    },
10    response::ClientResponse,
11    unified::UnifiedTransportConnection,
12    Connector,
13};
14
15pub struct ClientRequest<C = UnifiedTransportConnector> {
16    client: Client<C>,
17    builder: Builder,
18}
19
20impl<C> ClientRequest<C> {
21    pub fn new(client: Client<C>) -> Self {
22        Self {
23            client,
24            builder: Builder::new(),
25        }
26    }
27
28    pub fn method<T>(mut self, method: T) -> Self
29    where
30        Method: TryFrom<T>,
31        <Method as TryFrom<T>>::Error: Into<http::Error>,
32    {
33        self.builder = self.builder.method(method);
34        self
35    }
36
37    pub fn uri<T>(mut self, uri: T) -> Self
38    where
39        Uri: TryFrom<T>,
40        <Uri as TryFrom<T>>::Error: Into<http::Error>,
41    {
42        self.builder = self.builder.uri(uri);
43        self
44    }
45
46    pub fn header<K, V>(mut self, key: K, value: V) -> Self
47    where
48        HeaderName: TryFrom<K>,
49        <HeaderName as TryFrom<K>>::Error: Into<http::Error>,
50        HeaderValue: TryFrom<V>,
51        <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
52    {
53        self.builder = self.builder.header(key, value);
54        self
55    }
56
57    fn build_request(builder: Builder, body: HttpBody) -> crate::Result<http::Request<HttpBody>> {
58        let mut req = builder.version(http::Version::HTTP_11).body(body)?;
59        if let Some(host) = req.uri().host() {
60            let host = HeaderValue::try_from(host).map_err(http::Error::from)?;
61            let headers = req.headers_mut();
62            if !headers.contains_key(http::header::HOST) {
63                headers.insert(http::header::HOST, host);
64            }
65        }
66        Ok(req)
67    }
68}
69
70impl<C> ClientRequest<C>
71where
72    PooledConnector<C, Key, UnifiedTransportConnection>: Connector<
73        Key,
74        Connection = PooledConnection<Key, UnifiedTransportConnection>,
75        Error = crate::Error,
76    >,
77{
78    pub async fn send(self) -> crate::Result<ClientResponse> {
79        let request = Self::build_request(self.builder, HttpBody::fixed_body(None))?;
80        let resp = self.client.send_request(request).await?;
81        Ok(ClientResponse::new(resp))
82    }
83
84    pub async fn send_body(self, data: Bytes) -> crate::Result<ClientResponse> {
85        let request = Self::build_request(self.builder, HttpBody::fixed_body(Some(data)))?;
86        let resp = self.client.send_request(request).await?;
87        Ok(ClientResponse::new(resp))
88    }
89
90    pub async fn send_json<T: serde::Serialize>(self, data: &T) -> crate::Result<ClientResponse> {
91        let body: Bytes = serde_json::to_vec(data)?.into();
92        let builder = self.builder.header(
93            http::header::CONTENT_TYPE,
94            HeaderValue::from_static("application/json"),
95        );
96        let request = Self::build_request(builder, HttpBody::fixed_body(Some(body)))?;
97        let resp = self.client.send_request(request).await?;
98        Ok(ClientResponse::new(resp))
99    }
100}