cashweb_relay_client/
services.rs1use std::{fmt, pin::Pin};
4
5use futures_core::{
6 task::{Context, Poll},
7 Future,
8};
9use http::Method;
10use hyper::{
11 body::aggregate, http::header::AUTHORIZATION, Body, Error as HyperError, Request, Response,
12 StatusCode,
13};
14pub use hyper::{
15 client::{connect::Connect, HttpConnector},
16 Uri,
17};
18use prost::{DecodeError, Message as _};
19use thiserror::Error;
20use tower_service::Service;
21
22use super::RelayClient;
23use ::auth_wrapper::*;
24use relay::{MessagePage, Profile};
25
26type ResponseFuture<Response, Error> =
27 Pin<Box<dyn Future<Output = Result<Response, Error>> + 'static + Send>>;
28
29#[derive(Clone, Debug)]
31pub struct GetProfile;
32
33#[derive(Debug, Error)]
35pub enum GetProfileError<E: fmt::Debug + fmt::Display> {
36 #[error("profile decoding failure: {0}")]
38 ProfileDecode(DecodeError),
39 #[error("authwrapper decoding failure: {0}")]
41 AuthWrapperDecode(DecodeError),
42 #[error("processing body failed: {0}")]
44 Body(HyperError),
45 #[error("connection failure: {0}")]
47 Service(E),
48 #[error("unexpected status code: {0}")]
50 UnexpectedStatusCode(u16),
51}
52
53type FutResponse<Response, Error> =
54 Pin<Box<dyn Future<Output = Result<Response, Error>> + 'static + Send>>;
55
56impl<S> Service<(Uri, GetProfile)> for RelayClient<S>
57where
58 S: Service<Request<Body>, Response = Response<Body>>,
59 S: Send + Clone + 'static,
60 S::Future: Send,
61 S::Error: fmt::Debug + fmt::Display,
62{
63 type Response = AuthWrapper;
64 type Error = GetProfileError<S::Error>;
65 type Future = FutResponse<Self::Response, Self::Error>;
66
67 fn poll_ready(&mut self, context: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
68 self.inner_client
69 .poll_ready(context)
70 .map_err(GetProfileError::Service)
71 }
72
73 fn call(&mut self, (uri, _): (Uri, GetProfile)) -> Self::Future {
74 let mut client = self.inner_client.clone();
75 let http_request = Request::builder()
76 .method(Method::GET)
77 .uri(uri)
78 .body(Body::empty())
79 .unwrap(); let fut = async move {
81 let response = client
83 .call(http_request)
84 .await
85 .map_err(Self::Error::Service)?;
86
87 match response.status() {
90 StatusCode::OK => (),
91 code => return Err(Self::Error::UnexpectedStatusCode(code.as_u16())),
92 }
93
94 let body = response.into_body();
96 let buf = aggregate(body).await.map_err(Self::Error::Body)?;
97 let auth_wrapper = AuthWrapper::decode(buf).map_err(Self::Error::AuthWrapperDecode)?;
98
99 Ok(auth_wrapper)
100 };
101 Box::pin(fut)
102 }
103}
104
105#[derive(Clone, Debug, Error)]
107pub enum PutProfileError<E: fmt::Debug + fmt::Display> {
108 #[error("connection failure: {0}")]
110 Service(E),
111 #[error("unexpected status code: {0}")]
113 UnexpectedStatusCode(u16),
114}
115
116#[derive(Clone, Debug)]
118pub struct PutProfile {
119 pub token: String,
121 pub profile: Profile,
123}
124
125impl<S> Service<(Uri, PutProfile)> for RelayClient<S>
126where
127 S: Service<Request<Body>, Response = Response<Body>>,
128 S: Send + Clone + 'static,
129 S::Future: Send,
130 S::Error: fmt::Debug + fmt::Display,
131{
132 type Response = ();
133 type Error = PutProfileError<S::Error>;
134 type Future = FutResponse<Self::Response, Self::Error>;
135
136 fn poll_ready(&mut self, context: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
137 self.inner_client
138 .poll_ready(context)
139 .map_err(PutProfileError::Service)
140 }
141
142 fn call(&mut self, (uri, request): (Uri, PutProfile)) -> Self::Future {
143 let mut client = self.inner_client.clone();
144
145 let mut body = Vec::with_capacity(request.profile.encoded_len());
147 request.profile.encode(&mut body).unwrap();
148
149 let http_request = Request::builder()
150 .method(Method::PUT)
151 .uri(uri)
152 .header(AUTHORIZATION, request.token)
153 .body(Body::from(body))
154 .unwrap(); let fut = async move {
157 let response = client
159 .call(http_request)
160 .await
161 .map_err(Self::Error::Service)?;
162
163 match response.status() {
166 StatusCode::OK => (),
167 code => return Err(Self::Error::UnexpectedStatusCode(code.as_u16())),
168 }
169
170 Ok(())
171 };
172 Box::pin(fut)
173 }
174}
175
176#[derive(Debug, Error)]
178pub enum GetMessageError<E: fmt::Debug + fmt::Display> {
179 #[error("connection failure: {0}")]
181 Service(E),
182 #[error("unexpected status code: {0}")]
184 UnexpectedStatusCode(u16),
185 #[error("processing body failed: {0}")]
187 Body(HyperError),
188 #[error("messagepage decoding failure: {0}")]
190 MessagePageDecode(DecodeError),
191}
192
193#[derive(Clone, Debug)]
195pub struct GetMessages {
196 pub token: String,
198}
199
200impl<S> Service<(Uri, GetMessages)> for RelayClient<S>
201where
202 S: Service<Request<Body>, Response = Response<Body>>,
203 S: Send + Clone + 'static,
204 S::Future: Send,
205 S::Error: fmt::Debug + fmt::Display,
206{
207 type Response = MessagePage;
208 type Error = GetMessageError<S::Error>;
209 type Future = ResponseFuture<Self::Response, Self::Error>;
210
211 fn poll_ready(&mut self, context: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
212 self.inner_client
213 .poll_ready(context)
214 .map_err(GetMessageError::Service)
215 }
216
217 fn call(&mut self, (uri, request): (Uri, GetMessages)) -> Self::Future {
218 let mut client = self.inner_client.clone();
219
220 let http_request = Request::builder()
221 .method(Method::GET)
222 .uri(uri)
223 .header(AUTHORIZATION, request.token)
224 .body(Body::empty())
225 .unwrap(); let fut = async move {
228 let response = client
230 .call(http_request)
231 .await
232 .map_err(Self::Error::Service)?;
233
234 match response.status() {
237 StatusCode::OK => (),
238 code => return Err(Self::Error::UnexpectedStatusCode(code.as_u16())),
239 }
240
241 let body = response.into_body();
243 let buf = aggregate(body).await.map_err(Self::Error::Body)?;
244 let message_page = MessagePage::decode(buf).map_err(Self::Error::MessagePageDecode)?;
245
246 Ok(message_page)
247 };
248 Box::pin(fut)
249 }
250}