ruma_client/http_client/
hyper.rs

1use bytes::{Bytes, BytesMut};
2use http_body_util::{BodyExt as _, Full};
3use hyper_util::{
4    client::legacy::connect::{Connect, HttpConnector},
5    rt::TokioExecutor,
6};
7
8use super::{DefaultConstructibleHttpClient, HttpClient};
9
10/// A hyper HTTP client.
11///
12/// The default connector is rarely useful, since it doesn't support `https`.
13pub type Hyper<C = HttpConnector> = hyper_util::client::legacy::Client<C, Full<Bytes>>;
14
15/// A hyper HTTP client using native-tls for TLS support.
16#[cfg(feature = "hyper-native-tls")]
17pub type HyperNativeTls = Hyper<hyper_tls::HttpsConnector<HttpConnector>>;
18
19/// A hyper HTTP client using rustls for TLS support.
20///
21/// This client does not implement `DefaultConstructibleHttpClient`.
22/// To use it, you need to manually create an instance.
23#[cfg(feature = "hyper-rustls")]
24pub type HyperRustls = Hyper<hyper_rustls::HttpsConnector<HttpConnector>>;
25
26impl<C> HttpClient for Hyper<C>
27where
28    C: Connect + Clone + Send + Sync + 'static,
29{
30    type RequestBody = BytesMut;
31    type ResponseBody = Bytes;
32    type Error = Box<dyn std::error::Error + Send + Sync>;
33
34    async fn send_http_request(
35        &self,
36        req: http::Request<BytesMut>,
37    ) -> Result<http::Response<Bytes>, Self::Error> {
38        let (head, body) =
39            self.request(req.map(|body| Full::new(body.freeze()))).await?.into_parts();
40
41        // FIXME: Use aggregate instead of to_bytes once serde_json can parse from a reader at a
42        // comparable speed as reading from a slice: https://github.com/serde-rs/json/issues/160
43        let body = body.collect().await?.to_bytes();
44        Ok(http::Response::from_parts(head, body))
45    }
46}
47
48#[cfg(feature = "hyper")]
49impl DefaultConstructibleHttpClient for Hyper {
50    fn default() -> Self {
51        hyper_util::client::legacy::Client::builder(TokioExecutor::new())
52            .build(HttpConnector::new())
53    }
54}
55
56#[cfg(feature = "hyper-native-tls")]
57impl DefaultConstructibleHttpClient for HyperNativeTls {
58    fn default() -> Self {
59        hyper_util::client::legacy::Client::builder(TokioExecutor::new())
60            .build(hyper_tls::HttpsConnector::new())
61    }
62}