client: Replace send_request_with_url_params with send_customized_request

This commit is contained in:
Jonas Platte 2021-04-28 13:13:55 +02:00
parent 0fa686ac1d
commit ac78c855a8
No known key found for this signature in database
GPG Key ID: CC154DE0E30B7C67
2 changed files with 38 additions and 45 deletions

View File

@ -1,7 +1,7 @@
//! This module contains an abstraction for HTTP clients as well as friendly-named re-exports of //! This module contains an abstraction for HTTP clients as well as friendly-named re-exports of
//! client types that implement this trait. //! client types that implement this trait.
use std::{collections::BTreeMap, future::Future, pin::Pin}; use std::{future::Future, pin::Pin};
use async_trait::async_trait; use async_trait::async_trait;
use bytes::BufMut; use bytes::BufMut;
@ -61,29 +61,35 @@ pub trait HttpClientExt: HttpClient {
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>> {
Box::pin(crate::send_request_with_url_params( Box::pin(crate::send_customized_request(
self, self,
homeserver_url, homeserver_url,
access_token, access_token,
None,
request, request,
|_| {},
)) ))
} }
/// Send a strongly-typed matrix request to get back a strongly-typed response. /// Turn a strongly-typed matrix request into an `http::Request`, customize it and send it to
fn send_request_with_url_params<'a, R: OutgoingRequest + 'a>( /// get back a strongly-typed response.
// TODO: `R: 'a` and `F: 'a` should not be needed
fn send_customized_request<'a, R, F>(
&'a self, &'a self,
homeserver_url: &str, homeserver_url: &str,
access_token: SendAccessToken<'_>, access_token: SendAccessToken<'_>,
extra_params: BTreeMap<String, String>,
request: R, request: R,
) -> Pin<Box<dyn Future<Output = ResponseResult<Self, R>> + 'a>> { customize: F,
Box::pin(crate::send_request_with_url_params( ) -> Pin<Box<dyn Future<Output = ResponseResult<Self, R>> + 'a>>
where
R: OutgoingRequest + 'a,
F: FnOnce(&mut http::Request<Self::RequestBody>) + 'a,
{
Box::pin(crate::send_customized_request(
self, self,
homeserver_url, homeserver_url,
access_token, access_token,
Some(extra_params),
request, request,
customize,
)) ))
} }
} }

View File

@ -74,15 +74,11 @@
#![deny(missing_debug_implementations, missing_docs)] #![deny(missing_debug_implementations, missing_docs)]
use std::{ use std::{
collections::BTreeMap,
future::Future, future::Future,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use assign::assign;
use http::uri::Uri;
use ruma_api::{OutgoingRequest, SendAccessToken}; use ruma_api::{OutgoingRequest, SendAccessToken};
use ruma_serde::urlencoded;
// "Undo" rename from `Cargo.toml` that only serves to make `hyper-rustls` available as a Cargo // "Undo" rename from `Cargo.toml` that only serves to make `hyper-rustls` available as a Cargo
// feature name. // feature name.
@ -169,71 +165,62 @@ impl<C: HttpClient> Client<C> {
None => SendAccessToken::None, None => SendAccessToken::None,
}; };
send_request_with_url_params( send_customized_request(
&self.0.http_client, &self.0.http_client,
&self.0.homeserver_url, &self.0.homeserver_url,
send_access_token, send_access_token,
None,
request, request,
|_| {},
) )
.await .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.
pub async fn send_request_with_url_params<R: OutgoingRequest>( pub async fn send_customized_request<R, F>(
&self, &self,
extra_params: BTreeMap<String, String>,
request: R, request: R,
) -> Result<R::IncomingResponse, Error<C::Error, R::EndpointError>> { customize: F,
) -> Result<R::IncomingResponse, Error<C::Error, R::EndpointError>>
where
R: OutgoingRequest,
F: FnOnce(&mut http::Request<C::RequestBody>),
{
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() {
Some(at) => SendAccessToken::IfRequired(at), Some(at) => SendAccessToken::IfRequired(at),
None => SendAccessToken::None, None => SendAccessToken::None,
}; };
send_request_with_url_params( send_customized_request(
&self.0.http_client, &self.0.http_client,
&self.0.homeserver_url, &self.0.homeserver_url,
send_access_token, send_access_token,
Some(extra_params),
request, request,
customize,
) )
.await .await
} }
} }
fn send_request_with_url_params<'a, C, Request>( fn send_customized_request<'a, C, R, F>(
http_client: &'a C, http_client: &'a C,
homeserver_url: &str, homeserver_url: &str,
send_access_token: SendAccessToken<'_>, send_access_token: SendAccessToken<'_>,
extra_params: Option<BTreeMap<String, String>>, request: R,
request: Request, customize: F,
) -> impl Future<Output = Result<Request::IncomingResponse, Error<C::Error, Request::EndpointError>>> ) -> impl Future<Output = Result<R::IncomingResponse, Error<C::Error, R::EndpointError>>> + Send + 'a
+ Send
+ 'a
where where
C: HttpClient + ?Sized, C: HttpClient + ?Sized,
Request: OutgoingRequest, R: OutgoingRequest,
F: FnOnce(&mut http::Request<C::RequestBody>),
{ {
let res = request.try_into_http_request(homeserver_url, send_access_token); let mut http_req = request.try_into_http_request(homeserver_url, send_access_token);
if let Ok(req) = &mut http_req {
customize(req);
}
async move { async move {
let mut http_request = res?; let http_res = http_client.send_http_request(http_req?).await.map_err(Error::Response)?;
Ok(ruma_api::IncomingResponse::try_from_http_response(http_res)?)
if let Some(extra_params) = extra_params {
let extra_params = urlencoded::to_string(extra_params).unwrap();
let uri = http_request.uri_mut();
let new_path_and_query = match uri.query() {
Some(params) => format!("{}?{}&{}", uri.path(), params, extra_params),
None => format!("{}?{}", uri.path(), extra_params),
};
*uri = Uri::from_parts(assign!(uri.clone().into_parts(), {
path_and_query: Some(new_path_and_query.parse()?),
}))?;
}
let http_response =
http_client.send_http_request(http_request).await.map_err(Error::Response)?;
Ok(ruma_api::IncomingResponse::try_from_http_response(http_response)?)
} }
} }