1use std::sync::Arc;
2
3use http::{HeaderName, HeaderValue, Request, Response};
4use hyper::body::{Body, Incoming};
5
6use crate::Error;
7
8pub trait Client<B>
15where
16 B: Body + Send + 'static,
17 <B as Body>::Data: Send,
18 B::Error: Send + Sync + 'static,
19{
20 fn send(
26 &self,
27 req: Request<B>,
28 ) -> impl Future<Output = Result<Response<Incoming>, Error>> + Send;
29}
30
31pub trait ClientExt<B>: Client<B>
34where
35 B: Body + Send + 'static,
36 <B as Body>::Data: Send,
37 B::Error: Send + Sync + 'static,
38{
39 fn get(
45 &self,
46 url: &url::Url,
47 headers: impl IntoIterator<Item = (HeaderName, HeaderValue)>,
48 ) -> impl Future<Output = Result<Response<Incoming>, Error>>
49 where
50 B: Default,
51 {
52 let mut req = Request::get(url.as_str());
53
54 if let Some(hdrs) = req.headers_mut() {
55 hdrs.extend(crate::host_header(url));
56 hdrs.extend(headers);
57 }
58
59 async move {
60 let req = req.body(Default::default()).map_err(|e| {
61 tracing::error!(error = %e, "constructing request");
62 Error::InvalidParam
63 })?;
64
65 self.send(req).await
66 }
67 }
68
69 fn post(
75 &self,
76 url: &url::Url,
77 headers: impl IntoIterator<Item = (HeaderName, HeaderValue)>,
78 body: B,
79 ) -> impl Future<Output = Result<Response<Incoming>, Error>> {
80 let mut req = Request::post(url.as_str());
81
82 if let Some(hdrs) = req.headers_mut() {
83 hdrs.extend(crate::host_header(url));
84 hdrs.extend(headers);
85 }
86
87 async move {
88 let req = req.body(body).map_err(|e| {
89 tracing::error!(error = %e, "constructing request");
90 Error::InvalidParam
91 })?;
92
93 self.send(req).await
94 }
95 }
96}
97
98impl<T, B> ClientExt<B> for T
99where
100 T: Client<B>,
101 B: Body + Send + 'static,
102 <B as Body>::Data: Send,
103 B::Error: Send + Sync + 'static,
104{
105}
106
107impl<T, B> Client<B> for Arc<T>
108where
109 T: Client<B>,
110 B: Body + Send + 'static,
111 <B as Body>::Data: Send,
112 B::Error: Send + Sync + 'static,
113{
114 fn send(
115 &self,
116 req: Request<B>,
117 ) -> impl Future<Output = Result<Response<Incoming>, Error>> + Send {
118 self.as_ref().send(req)
119 }
120}
121
122impl<T, B> Client<B> for &T
123where
124 T: Client<B>,
125 B: Body + Send + 'static,
126 <B as Body>::Data: Send,
127 B::Error: Send + Sync + 'static,
128{
129 fn send(
130 &self,
131 req: Request<B>,
132 ) -> impl Future<Output = Result<Response<Incoming>, Error>> + Send {
133 (**self).send(req)
134 }
135}
136
137impl<T, B> Client<B> for &mut T
138where
139 T: Client<B>,
140 B: Body + Send + 'static,
141 <B as Body>::Data: Send,
142 B::Error: Send + Sync + 'static,
143{
144 fn send(
145 &self,
146 req: Request<B>,
147 ) -> impl Future<Output = Result<Response<Incoming>, Error>> + Send {
148 (**self).send(req)
149 }
150}