client: Allow request customization to be fallible

This commit is contained in:
Jonas Platte 2021-04-28 14:26:14 +02:00
parent 9bbad70592
commit 20dfd7c328
No known key found for this signature in database
GPG Key ID: CC154DE0E30B7C67
2 changed files with 31 additions and 17 deletions

View File

@ -7,7 +7,7 @@ use async_trait::async_trait;
use bytes::BufMut; use bytes::BufMut;
use ruma_api::{OutgoingRequest, SendAccessToken}; use ruma_api::{OutgoingRequest, SendAccessToken};
use crate::ResponseResult; use crate::{ResponseError, ResponseResult};
#[cfg(feature = "hyper")] #[cfg(feature = "hyper")]
mod hyper; mod hyper;
@ -33,7 +33,7 @@ pub trait HttpClient: Sync {
type ResponseBody: AsRef<[u8]>; type ResponseBody: AsRef<[u8]>;
/// The error type for the `send_request` function. /// The error type for the `send_request` function.
type Error: Unpin; type Error: Send + Unpin;
/// Send an `http::Request` to get back an `http::Response`. /// Send an `http::Request` to get back an `http::Response`.
async fn send_http_request( async fn send_http_request(
@ -60,8 +60,11 @@ pub trait HttpClientExt: HttpClient {
homeserver_url: &str, homeserver_url: &str,
access_token: SendAccessToken<'_>, access_token: SendAccessToken<'_>,
request: R, request: R,
) -> Pin<Box<dyn Future<Output = ResponseResult<Self, R>> + 'a>> { ) -> Pin<Box<dyn Future<Output = ResponseResult<Self, R>> + 'a>>
self.send_customized_request(homeserver_url, access_token, request, |_| {}) where
<R as OutgoingRequest>::EndpointError: Send,
{
self.send_customized_request(homeserver_url, access_token, request, |_| Ok(()))
} }
/// Turn a strongly-typed matrix request into an `http::Request`, customize it and send it to /// Turn a strongly-typed matrix request into an `http::Request`, customize it and send it to
@ -76,7 +79,8 @@ pub trait HttpClientExt: HttpClient {
) -> Pin<Box<dyn Future<Output = ResponseResult<Self, R>> + 'a>> ) -> Pin<Box<dyn Future<Output = ResponseResult<Self, R>> + 'a>>
where where
R: OutgoingRequest + 'a, R: OutgoingRequest + 'a,
F: FnOnce(&mut http::Request<Self::RequestBody>) + 'a, <R as OutgoingRequest>::EndpointError: Send,
F: FnOnce(&mut http::Request<Self::RequestBody>) -> Result<(), ResponseError<Self, R>> + 'a,
{ {
Box::pin(crate::send_customized_request( Box::pin(crate::send_customized_request(
self, self,

View File

@ -95,11 +95,13 @@ pub use self::{
http_client::{DefaultConstructibleHttpClient, HttpClient, HttpClientExt}, http_client::{DefaultConstructibleHttpClient, HttpClient, HttpClientExt},
}; };
/// The error type for sending the request `R` with the http client `C`.
pub type ResponseError<C, R> =
Error<<C as HttpClient>::Error, <R as OutgoingRequest>::EndpointError>;
/// The result of sending the request `R` with the http client `C`. /// The result of sending the request `R` with the http client `C`.
pub type ResponseResult<C, R> = Result< pub type ResponseResult<C, R> =
<R as OutgoingRequest>::IncomingResponse, Result<<R as OutgoingRequest>::IncomingResponse, ResponseError<C, R>>;
Error<<C as HttpClient>::Error, <R as OutgoingRequest>::EndpointError>,
>;
/// A client for the Matrix client-server API. /// A client for the Matrix client-server API.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -155,8 +157,11 @@ impl<C: DefaultConstructibleHttpClient> Client<C> {
impl<C: HttpClient> Client<C> { impl<C: HttpClient> Client<C> {
/// Makes a request to a Matrix API endpoint. /// Makes a request to a Matrix API endpoint.
pub async fn send_request<R: OutgoingRequest>(&self, request: R) -> ResponseResult<C, R> { pub async fn send_request<R: OutgoingRequest>(&self, request: R) -> ResponseResult<C, R>
self.send_customized_request(request, |_| {}).await where
<R as OutgoingRequest>::EndpointError: Send,
{
self.send_customized_request(request, |_| Ok(())).await
} }
/// Makes a request to a Matrix API endpoint including additional URL parameters. /// Makes a request to a Matrix API endpoint including additional URL parameters.
@ -167,7 +172,8 @@ impl<C: HttpClient> Client<C> {
) -> ResponseResult<C, R> ) -> ResponseResult<C, R>
where where
R: OutgoingRequest, R: OutgoingRequest,
F: FnOnce(&mut http::Request<C::RequestBody>), <R as OutgoingRequest>::EndpointError: Send,
F: FnOnce(&mut http::Request<C::RequestBody>) -> Result<(), ResponseError<C, R>>,
{ {
let access_token = self.access_token(); let access_token = self.access_token();
let send_access_token = match access_token.as_deref() { let send_access_token = match access_token.as_deref() {
@ -196,12 +202,16 @@ fn send_customized_request<'a, C, R, F>(
where where
C: HttpClient + ?Sized, C: HttpClient + ?Sized,
R: OutgoingRequest, R: OutgoingRequest,
F: FnOnce(&mut http::Request<C::RequestBody>), <R as OutgoingRequest>::EndpointError: Send,
F: FnOnce(&mut http::Request<C::RequestBody>) -> Result<(), ResponseError<C, R>>,
{ {
let mut http_req = request.try_into_http_request(homeserver_url, send_access_token); let http_req = request
if let Ok(req) = &mut http_req { .try_into_http_request(homeserver_url, send_access_token)
customize(req); .map_err(ResponseError::<C, R>::from)
} .and_then(|mut req| {
customize(&mut req)?;
Ok(req)
});
async move { async move {
let http_res = http_client.send_http_request(http_req?).await.map_err(Error::Response)?; let http_res = http_client.send_http_request(http_req?).await.map_err(Error::Response)?;