diff --git a/crates/ruma-client/src/client_api.rs b/crates/ruma-client/src/client.rs similarity index 56% rename from crates/ruma-client/src/client_api.rs rename to crates/ruma-client/src/client.rs index f5ef052d..12701a7d 100644 --- a/crates/ruma-client/src/client_api.rs +++ b/crates/ruma-client/src/client.rs @@ -1,9 +1,12 @@ -use std::time::Duration; +use std::{ + sync::{Arc, Mutex}, + time::Duration, +}; use assign::assign; use async_stream::try_stream; use futures_core::stream::Stream; -use ruma_api::MatrixVersion; +use ruma_api::{MatrixVersion, OutgoingRequest, SendAccessToken}; use ruma_client_api::{ account::register::{self, RegistrationKind}, session::login::{self, v3::LoginInfo}, @@ -11,12 +14,117 @@ use ruma_client_api::{ uiaa::UserIdentifier, }; 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(Arc>); + +/// Data contained in Client's Rc +#[derive(Debug)] +struct ClientData { + /// The URL of the homeserver to connect to. + homeserver_url: String, + + /// The underlying HTTP client. + http_client: C, + + /// User session data. + access_token: Mutex>, +} + +impl Client { + /// 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, + ) -> 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 { + self.0.access_token.lock().expect("session mutex was poisoned").clone() + } +} + +impl Client { + /// Creates a new client based on a default-constructed hyper HTTP client. + pub fn new(homeserver_url: String, access_token: Option) -> Self { + Self(Arc::new(ClientData { + homeserver_url, + http_client: DefaultConstructibleHttpClient::default(), + access_token: Mutex::new(access_token), + })) + } +} -/// Client-API specific functionality of `Client`. impl Client { + /// Makes a request to a Matrix API endpoint. + pub async fn send_request( + &self, + request: R, + for_versions: &[MatrixVersion], + ) -> ResponseResult { + 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( + &self, + request: R, + for_versions: &[MatrixVersion], + customize: F, + ) -> ResponseResult + where + R: OutgoingRequest, + F: FnOnce(&mut http::Request) -> Result<(), ResponseError>, + { + 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( + &self, + user_id: &UserId, + request: R, + for_versions: &[MatrixVersion], + ) -> ResponseResult { + self.send_customized_request(request, for_versions, add_user_id_to_query::(user_id)) + .await + } + /// Log in with a username and password. /// /// In contrast to [`send_request`][Self::send_request], this method stores the access token diff --git a/crates/ruma-client/src/lib.rs b/crates/ruma-client/src/lib.rs index 5044d529..5bb1b8e0 100644 --- a/crates/ruma-client/src/lib.rs +++ b/crates/ruma-client/src/lib.rs @@ -96,11 +96,7 @@ #![warn(missing_docs)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -use std::{ - any::type_name, - future::Future, - sync::{Arc, Mutex}, -}; +use std::{any::type_name, future::Future}; use ruma_api::{MatrixVersion, OutgoingRequest, SendAccessToken}; use ruma_identifiers::UserId; @@ -114,10 +110,12 @@ extern crate hyper_rustls_crate as hyper_rustls; extern crate isahc_crate as isahc; #[cfg(feature = "client-api")] -mod client_api; +mod client; mod error; pub mod http_client; +#[cfg(feature = "client-api")] +pub use self::client::Client; pub use self::{ error::Error, http_client::{DefaultConstructibleHttpClient, HttpClient, HttpClientExt}, @@ -131,111 +129,6 @@ pub type ResponseError = pub type ResponseResult = Result<::IncomingResponse, ResponseError>; -/// A client for the Matrix client-server API. -#[derive(Clone, Debug)] -pub struct Client(Arc>); - -/// Data contained in Client's Rc -#[derive(Debug)] -struct ClientData { - /// The URL of the homeserver to connect to. - homeserver_url: String, - - /// The underlying HTTP client. - http_client: C, - - /// User session data. - access_token: Mutex>, -} - -impl Client { - /// 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, - ) -> 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 { - self.0.access_token.lock().expect("session mutex was poisoned").clone() - } -} - -impl Client { - /// Creates a new client based on a default-constructed hyper HTTP client. - pub fn new(homeserver_url: String, access_token: Option) -> Self { - Self(Arc::new(ClientData { - homeserver_url, - http_client: DefaultConstructibleHttpClient::default(), - access_token: Mutex::new(access_token), - })) - } -} - -impl Client { - /// Makes a request to a Matrix API endpoint. - pub async fn send_request( - &self, - request: R, - for_versions: &[MatrixVersion], - ) -> ResponseResult { - 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( - &self, - request: R, - for_versions: &[MatrixVersion], - customize: F, - ) -> ResponseResult - where - R: OutgoingRequest, - F: FnOnce(&mut http::Request) -> Result<(), ResponseError>, - { - 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( - &self, - user_id: &UserId, - request: R, - for_versions: &[MatrixVersion], - ) -> ResponseResult { - self.send_customized_request(request, for_versions, add_user_id_to_query::(user_id)) - .await - } -} - fn send_customized_request<'a, C, R, F>( http_client: &'a C, homeserver_url: &str,