client: Move the entire Client behind the client-api feature

This commit is contained in:
Jonas Platte 2022-02-18 22:26:44 +01:00
parent 8743a7791d
commit b5ddd7effd
No known key found for this signature in database
GPG Key ID: CC154DE0E30B7C67
2 changed files with 117 additions and 116 deletions

View File

@ -1,9 +1,12 @@
use std::time::Duration; use std::{
sync::{Arc, Mutex},
time::Duration,
};
use assign::assign; use assign::assign;
use async_stream::try_stream; use async_stream::try_stream;
use futures_core::stream::Stream; use futures_core::stream::Stream;
use ruma_api::MatrixVersion; use ruma_api::{MatrixVersion, OutgoingRequest, SendAccessToken};
use ruma_client_api::{ use ruma_client_api::{
account::register::{self, RegistrationKind}, account::register::{self, RegistrationKind},
session::login::{self, v3::LoginInfo}, session::login::{self, v3::LoginInfo},
@ -11,12 +14,117 @@ use ruma_client_api::{
uiaa::UserIdentifier, uiaa::UserIdentifier,
}; };
use ruma_common::presence::PresenceState; use ruma_common::presence::PresenceState;
use ruma_identifiers::DeviceId; use ruma_identifiers::{DeviceId, UserId};
use super::{Client, Error, HttpClient}; use crate::{
add_user_id_to_query, send_customized_request, DefaultConstructibleHttpClient, Error,
HttpClient, ResponseError, ResponseResult,
};
/// A client for the Matrix client-server API.
#[derive(Clone, Debug)]
pub struct Client<C>(Arc<ClientData<C>>);
/// Data contained in Client's Rc
#[derive(Debug)]
struct ClientData<C> {
/// The URL of the homeserver to connect to.
homeserver_url: String,
/// The underlying HTTP client.
http_client: C,
/// User session data.
access_token: Mutex<Option<String>>,
}
impl<C> Client<C> {
/// Creates a new client using the given underlying HTTP client.
///
/// This allows the user to configure the details of HTTP as desired.
pub fn with_http_client(
http_client: C,
homeserver_url: String,
access_token: Option<String>,
) -> Self {
Self(Arc::new(ClientData {
homeserver_url,
http_client,
access_token: Mutex::new(access_token),
}))
}
/// Get a copy of the current `access_token`, if any.
///
/// Useful for serializing and persisting the session to be restored later.
pub fn access_token(&self) -> Option<String> {
self.0.access_token.lock().expect("session mutex was poisoned").clone()
}
}
impl<C: DefaultConstructibleHttpClient> Client<C> {
/// Creates a new client based on a default-constructed hyper HTTP client.
pub fn new(homeserver_url: String, access_token: Option<String>) -> Self {
Self(Arc::new(ClientData {
homeserver_url,
http_client: DefaultConstructibleHttpClient::default(),
access_token: Mutex::new(access_token),
}))
}
}
/// Client-API specific functionality of `Client`.
impl<C: HttpClient> 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,
for_versions: &[MatrixVersion],
) -> ResponseResult<C, R> {
self.send_customized_request(request, for_versions, |_| Ok(())).await
}
/// Makes a request to a Matrix API endpoint including additional URL parameters.
pub async fn send_customized_request<R, F>(
&self,
request: R,
for_versions: &[MatrixVersion],
customize: F,
) -> ResponseResult<C, R>
where
R: OutgoingRequest,
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() {
Some(at) => SendAccessToken::IfRequired(at),
None => SendAccessToken::None,
};
send_customized_request(
&self.0.http_client,
&self.0.homeserver_url,
send_access_token,
for_versions,
request,
customize,
)
.await
}
/// Makes a request to a Matrix API endpoint as a virtual user.
///
/// This method is meant to be used by application services when interacting with the
/// client-server API.
pub async fn send_request_as<R: OutgoingRequest>(
&self,
user_id: &UserId,
request: R,
for_versions: &[MatrixVersion],
) -> ResponseResult<C, R> {
self.send_customized_request(request, for_versions, add_user_id_to_query::<C, R>(user_id))
.await
}
/// Log in with a username and password. /// Log in with a username and password.
/// ///
/// In contrast to [`send_request`][Self::send_request], this method stores the access token /// In contrast to [`send_request`][Self::send_request], this method stores the access token

View File

@ -96,11 +96,7 @@
#![warn(missing_docs)] #![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))]
use std::{ use std::{any::type_name, future::Future};
any::type_name,
future::Future,
sync::{Arc, Mutex},
};
use ruma_api::{MatrixVersion, OutgoingRequest, SendAccessToken}; use ruma_api::{MatrixVersion, OutgoingRequest, SendAccessToken};
use ruma_identifiers::UserId; use ruma_identifiers::UserId;
@ -114,10 +110,12 @@ extern crate hyper_rustls_crate as hyper_rustls;
extern crate isahc_crate as isahc; extern crate isahc_crate as isahc;
#[cfg(feature = "client-api")] #[cfg(feature = "client-api")]
mod client_api; mod client;
mod error; mod error;
pub mod http_client; pub mod http_client;
#[cfg(feature = "client-api")]
pub use self::client::Client;
pub use self::{ pub use self::{
error::Error, error::Error,
http_client::{DefaultConstructibleHttpClient, HttpClient, HttpClientExt}, http_client::{DefaultConstructibleHttpClient, HttpClient, HttpClientExt},
@ -131,111 +129,6 @@ pub type ResponseError<C, R> =
pub type ResponseResult<C, R> = pub type ResponseResult<C, R> =
Result<<R as OutgoingRequest>::IncomingResponse, ResponseError<C, R>>; Result<<R as OutgoingRequest>::IncomingResponse, ResponseError<C, R>>;
/// A client for the Matrix client-server API.
#[derive(Clone, Debug)]
pub struct Client<C>(Arc<ClientData<C>>);
/// Data contained in Client's Rc
#[derive(Debug)]
struct ClientData<C> {
/// The URL of the homeserver to connect to.
homeserver_url: String,
/// The underlying HTTP client.
http_client: C,
/// User session data.
access_token: Mutex<Option<String>>,
}
impl<C> Client<C> {
/// Creates a new client using the given underlying HTTP client.
///
/// This allows the user to configure the details of HTTP as desired.
pub fn with_http_client(
http_client: C,
homeserver_url: String,
access_token: Option<String>,
) -> Self {
Self(Arc::new(ClientData {
homeserver_url,
http_client,
access_token: Mutex::new(access_token),
}))
}
/// Get a copy of the current `access_token`, if any.
///
/// Useful for serializing and persisting the session to be restored later.
pub fn access_token(&self) -> Option<String> {
self.0.access_token.lock().expect("session mutex was poisoned").clone()
}
}
impl<C: DefaultConstructibleHttpClient> Client<C> {
/// Creates a new client based on a default-constructed hyper HTTP client.
pub fn new(homeserver_url: String, access_token: Option<String>) -> Self {
Self(Arc::new(ClientData {
homeserver_url,
http_client: DefaultConstructibleHttpClient::default(),
access_token: Mutex::new(access_token),
}))
}
}
impl<C: HttpClient> Client<C> {
/// Makes a request to a Matrix API endpoint.
pub async fn send_request<R: OutgoingRequest>(
&self,
request: R,
for_versions: &[MatrixVersion],
) -> ResponseResult<C, R> {
self.send_customized_request(request, for_versions, |_| Ok(())).await
}
/// Makes a request to a Matrix API endpoint including additional URL parameters.
pub async fn send_customized_request<R, F>(
&self,
request: R,
for_versions: &[MatrixVersion],
customize: F,
) -> ResponseResult<C, R>
where
R: OutgoingRequest,
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() {
Some(at) => SendAccessToken::IfRequired(at),
None => SendAccessToken::None,
};
send_customized_request(
&self.0.http_client,
&self.0.homeserver_url,
send_access_token,
for_versions,
request,
customize,
)
.await
}
/// Makes a request to a Matrix API endpoint as a virtual user.
///
/// This method is meant to be used by application services when interacting with the
/// client-server API.
pub async fn send_request_as<R: OutgoingRequest>(
&self,
user_id: &UserId,
request: R,
for_versions: &[MatrixVersion],
) -> ResponseResult<C, R> {
self.send_customized_request(request, for_versions, add_user_id_to_query::<C, R>(user_id))
.await
}
}
fn send_customized_request<'a, C, R, F>( fn send_customized_request<'a, C, R, F>(
http_client: &'a C, http_client: &'a C,
homeserver_url: &str, homeserver_url: &str,