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 ruma_api::{OutgoingRequest, SendAccessToken};
use crate::ResponseResult;
use crate::{ResponseError, ResponseResult};
#[cfg(feature = "hyper")]
mod hyper;
@ -33,7 +33,7 @@ pub trait HttpClient: Sync {
type ResponseBody: AsRef<[u8]>;
/// 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`.
async fn send_http_request(
@ -60,8 +60,11 @@ pub trait HttpClientExt: HttpClient {
homeserver_url: &str,
access_token: SendAccessToken<'_>,
request: R,
) -> Pin<Box<dyn Future<Output = ResponseResult<Self, R>> + 'a>> {
self.send_customized_request(homeserver_url, access_token, request, |_| {})
) -> Pin<Box<dyn Future<Output = ResponseResult<Self, R>> + 'a>>
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
@ -76,7 +79,8 @@ pub trait HttpClientExt: HttpClient {
) -> Pin<Box<dyn Future<Output = ResponseResult<Self, R>> + 'a>>
where
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(
self,

View File

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