Skip to main content

ruma_client/client/
builder.rs

1use std::sync::{Arc, Mutex};
2
3use ruma::api::{
4    SupportedVersions, auth_scheme::SendAccessToken, client::discovery::get_supported_versions,
5};
6
7use super::{Client, ClientData, TokenMode};
8use crate::{DefaultConstructibleHttpClient, Error, HttpClient, HttpClientExt};
9
10/// A [`Client`] builder.
11///
12/// This type can be used to construct a `Client` through a few method calls.
13pub struct ClientBuilder {
14    homeserver_url: Option<String>,
15    access_token: Option<String>,
16    token_mode: TokenMode,
17    supported_matrix_versions: Option<SupportedVersions>,
18}
19
20impl ClientBuilder {
21    pub(super) fn new() -> Self {
22        Self {
23            homeserver_url: None,
24            access_token: None,
25            token_mode: TokenMode::default(),
26            supported_matrix_versions: None,
27        }
28    }
29
30    /// Set the homeserver URL.
31    ///
32    /// The homeserver URL must be set before calling [`build()`][Self::build] or
33    /// [`http_client()`][Self::http_client].
34    pub fn homeserver_url(self, url: String) -> Self {
35        Self { homeserver_url: Some(url), ..self }
36    }
37
38    /// Set the access token.
39    pub fn access_token(self, access_token: Option<String>) -> Self {
40        Self { access_token, ..self }
41    }
42
43    /// Set how access tokens should be handled when making requests.
44    pub fn token_mode(self, token_mode: TokenMode) -> Self {
45        Self { token_mode, ..self }
46    }
47
48    /// Set the supported Matrix versions.
49    ///
50    /// This method generally *shouldn't* be called. The [`build()`][Self::build] or
51    /// [`http_client()`][Self::http_client] method will take care of doing a
52    /// [`get_supported_versions`] request to find out about the supported versions.
53    pub fn supported_matrix_versions(self, versions: SupportedVersions) -> Self {
54        Self { supported_matrix_versions: Some(versions), ..self }
55    }
56
57    /// Finish building the [`Client`].
58    ///
59    /// Uses [`DefaultConstructibleHttpClient::default()`] to create an HTTP client instance.
60    /// Unless the supported Matrix versions were manually set via
61    /// [`supported_matrix_versions`][Self::supported_matrix_versions], this will do a
62    /// [`get_supported_versions`] request to find out about the supported versions.
63    pub async fn build<C>(self) -> Result<Client<C>, Error<C::Error, ruma::api::error::Error>>
64    where
65        C: DefaultConstructibleHttpClient,
66    {
67        self.http_client(C::default()).await
68    }
69
70    /// Set the HTTP client to finish building the [`Client`].
71    ///
72    /// Unless the supported Matrix versions were manually set via
73    /// [`supported_matrix_versions`][Self::supported_matrix_versions], this will do a
74    /// [`get_supported_versions`] request to find out about the supported versions.
75    pub async fn http_client<C>(
76        self,
77        http_client: C,
78    ) -> Result<Client<C>, Error<C::Error, ruma::api::error::Error>>
79    where
80        C: HttpClient,
81    {
82        let homeserver_url = self
83            .homeserver_url
84            .expect("homeserver URL has to be set prior to calling .build() or .http_client()");
85
86        let supported_matrix_versions = match self.supported_matrix_versions {
87            Some(versions) => versions,
88            None => http_client
89                .send_matrix_request(
90                    &homeserver_url,
91                    SendAccessToken::None,
92                    (),
93                    get_supported_versions::Request::new(),
94                )
95                .await?
96                .as_supported_versions(),
97        };
98
99        Ok(Client(Arc::new(ClientData {
100            homeserver_url,
101            http_client,
102            access_token: Mutex::new(self.access_token),
103            token_mode: self.token_mode,
104            supported_matrix_versions,
105        })))
106    }
107}