mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-18 13:40:55 -04:00
feat(sdk): Fetch supported matrix versions from server in initialization
This commit is contained in:
@@ -10,7 +10,7 @@ use matrix_sdk::{
|
||||
};
|
||||
use matrix_sdk_appservice::*;
|
||||
use matrix_sdk_test::{appservice::TransactionBuilder, async_test, EventsJson};
|
||||
use ruma::room_id;
|
||||
use ruma::{api::MatrixVersion, room_id};
|
||||
use serde_json::json;
|
||||
use warp::{Filter, Reply};
|
||||
|
||||
@@ -35,7 +35,7 @@ async fn appservice(registration: Option<Registration>) -> Result<AppService> {
|
||||
|
||||
let client_builder = Client::builder()
|
||||
.request_config(RequestConfig::default().disable_retry())
|
||||
.check_supported_versions(false);
|
||||
.server_versions([MatrixVersion::V1_0]);
|
||||
|
||||
AppService::with_client_builder(
|
||||
homeserver_url.as_ref(),
|
||||
|
||||
@@ -3,7 +3,7 @@ use quote::{format_ident, quote, ToTokens};
|
||||
use syn::{self, parse_macro_input};
|
||||
|
||||
/// Attribute to use `wasm_bindgen_test` for wasm32 targets and `tokio::test`
|
||||
/// for everything else with async-support and custom result-tyupes
|
||||
/// for everything else with async-support and custom result-types
|
||||
#[proc_macro_attribute]
|
||||
pub fn async_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let fun = parse_macro_input!(item as syn::ItemFn);
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use matrix_sdk_base::{locks::RwLock, store::StoreConfig, BaseClient, StateStore};
|
||||
use ruma::{api::client::discover::discover_homeserver, ServerName, UserId};
|
||||
use ruma::{
|
||||
api::{
|
||||
client::discover::{discover_homeserver, get_supported_versions},
|
||||
MatrixVersion,
|
||||
},
|
||||
ServerName, UserId,
|
||||
};
|
||||
use thiserror::Error;
|
||||
use url::Url;
|
||||
|
||||
@@ -58,7 +64,7 @@ pub struct ClientBuilder {
|
||||
request_config: RequestConfig,
|
||||
respect_login_well_known: bool,
|
||||
appservice_mode: bool,
|
||||
check_supported_versions: bool,
|
||||
server_versions: Option<Arc<[MatrixVersion]>>,
|
||||
}
|
||||
|
||||
impl ClientBuilder {
|
||||
@@ -70,7 +76,7 @@ impl ClientBuilder {
|
||||
request_config: Default::default(),
|
||||
respect_login_well_known: true,
|
||||
appservice_mode: false,
|
||||
check_supported_versions: true,
|
||||
server_versions: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,13 +248,12 @@ impl ClientBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify whether the homeserver functionality should be checked through a
|
||||
/// get_supported_versions request.
|
||||
/// Specify the Matrix versions supported by the homeserver manually, rather
|
||||
/// than `build()` doing it using a `get_supported_versions` request.
|
||||
///
|
||||
/// This is helpful for test code that doesn't care to mock that endpoint.
|
||||
#[doc(hidden)]
|
||||
pub fn check_supported_versions(mut self, value: bool) -> Self {
|
||||
self.check_supported_versions = value;
|
||||
pub fn server_versions(mut self, value: impl IntoIterator<Item = MatrixVersion>) -> Self {
|
||||
self.server_versions = Some(value.into_iter().collect());
|
||||
self
|
||||
}
|
||||
|
||||
@@ -267,8 +272,8 @@ impl ClientBuilder {
|
||||
/// URL
|
||||
/// * HTTP error: If you supplied a user ID instead of a homeserver URL, a
|
||||
/// server discovery request is made which can fail; if you didn't set
|
||||
/// [`check_supported_versions(false)`][Self::check_supported_versions],
|
||||
/// that amounts to another request that can fail
|
||||
/// [`server_versions(false)`][Self::server_versions], that amounts to
|
||||
/// another request that can fail
|
||||
pub async fn build(self) -> Result<Client, ClientBuildError> {
|
||||
let homeserver_cfg = self.homeserver_cfg.ok_or(ClientBuildError::MissingHomeserver)?;
|
||||
|
||||
@@ -301,8 +306,13 @@ impl ClientBuilder {
|
||||
HomeserverConfig::ServerName(server_name) => {
|
||||
let homeserver = homeserver_from_name(&server_name)?;
|
||||
let http_client = mk_http_client(Arc::new(RwLock::new(homeserver)));
|
||||
let well_known =
|
||||
http_client.send(discover_homeserver::Request::new(), None).await?;
|
||||
let well_known = http_client
|
||||
.send(
|
||||
discover_homeserver::Request::new(),
|
||||
None,
|
||||
[MatrixVersion::V1_0].into_iter().collect(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
well_known.homeserver.base_url
|
||||
}
|
||||
@@ -311,10 +321,24 @@ impl ClientBuilder {
|
||||
let homeserver = Arc::new(RwLock::new(Url::parse(&homeserver)?));
|
||||
let http_client = mk_http_client(homeserver.clone());
|
||||
|
||||
let server_versions = match self.server_versions {
|
||||
Some(vs) => vs,
|
||||
None => http_client
|
||||
.send(
|
||||
get_supported_versions::Request::new(),
|
||||
Some(RequestConfig::short_retry()),
|
||||
[MatrixVersion::V1_0].into_iter().collect(),
|
||||
)
|
||||
.await?
|
||||
.known_versions()
|
||||
.collect(),
|
||||
};
|
||||
|
||||
let inner = Arc::new(ClientInner {
|
||||
homeserver,
|
||||
http_client,
|
||||
base_client,
|
||||
server_versions,
|
||||
#[cfg(feature = "encryption")]
|
||||
group_session_locks: Default::default(),
|
||||
#[cfg(feature = "encryption")]
|
||||
@@ -328,13 +352,8 @@ impl ClientBuilder {
|
||||
respect_login_well_known: self.respect_login_well_known,
|
||||
sync_beat: event_listener::Event::new(),
|
||||
});
|
||||
let client = Client { inner };
|
||||
|
||||
if self.check_supported_versions {
|
||||
client.get_supported_versions().await?;
|
||||
}
|
||||
|
||||
Ok(client)
|
||||
Ok(Client { inner })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ use ruma::{
|
||||
capabilities::{get_capabilities, Capabilities},
|
||||
device::{delete_devices, get_devices},
|
||||
directory::{get_public_rooms, get_public_rooms_filtered},
|
||||
discover::get_supported_versions,
|
||||
filter::{create_filter::v3::Request as FilterUploadRequest, FilterDefinition},
|
||||
media::{create_content, get_content, get_content_thumbnail},
|
||||
membership::{join_room_by_id, join_room_by_id_or_alias},
|
||||
@@ -124,6 +123,8 @@ pub(crate) struct ClientInner {
|
||||
http_client: HttpClient,
|
||||
/// User session data.
|
||||
base_client: BaseClient,
|
||||
/// The Matrix versions the server supports (well-known ones only)
|
||||
server_versions: Arc<[MatrixVersion]>,
|
||||
/// Locks making sure we only have one group session sharing request in
|
||||
/// flight per room.
|
||||
#[cfg(feature = "encryption")]
|
||||
@@ -208,29 +209,6 @@ impl Client {
|
||||
*homeserver = homeserver_url;
|
||||
}
|
||||
|
||||
/// Get the versions supported by the homeserver.
|
||||
///
|
||||
/// This method should be used to check that a server is a valid Matrix
|
||||
/// homeserver.
|
||||
///
|
||||
/// # Example
|
||||
/// ```no_run
|
||||
/// # use futures::executor::block_on;
|
||||
/// # block_on(async {
|
||||
/// use matrix_sdk::{Client};
|
||||
/// use url::Url;
|
||||
///
|
||||
/// let homeserver = Url::parse("http://example.com")?;
|
||||
/// let client = Client::new(homeserver).await?;
|
||||
///
|
||||
/// // Check that it is a valid homeserver.
|
||||
/// client.get_supported_versions().await?;
|
||||
/// # Result::<_, anyhow::Error>::Ok(()) });
|
||||
/// ```
|
||||
pub async fn get_supported_versions(&self) -> HttpResult<get_supported_versions::Response> {
|
||||
self.send(get_supported_versions::Request::new(), Some(RequestConfig::short_retry())).await
|
||||
}
|
||||
|
||||
/// Get the capabilities of the homeserver.
|
||||
///
|
||||
/// This method should be used to check what features are supported by the
|
||||
@@ -371,7 +349,7 @@ impl Client {
|
||||
/// # block_on(async {
|
||||
/// # let client = matrix_sdk::Client::builder()
|
||||
/// # .homeserver_url(homeserver)
|
||||
/// # .check_supported_versions(false)
|
||||
/// # .server_versions([ruma::api::MatrixVersion::V1_0])
|
||||
/// # .build()
|
||||
/// # .await
|
||||
/// # .unwrap();
|
||||
@@ -490,7 +468,7 @@ impl Client {
|
||||
/// # block_on(async {
|
||||
/// # let client = matrix_sdk::Client::builder()
|
||||
/// # .homeserver_url(homeserver)
|
||||
/// # .check_supported_versions(false)
|
||||
/// # .server_versions([ruma::api::MatrixVersion::V1_0])
|
||||
/// # .build()
|
||||
/// # .await
|
||||
/// # .unwrap();
|
||||
@@ -658,15 +636,13 @@ impl Client {
|
||||
.try_into_http_request::<Vec<u8>>(
|
||||
homeserver.as_str(),
|
||||
SendAccessToken::None,
|
||||
// FIXME: Use versions reported by server
|
||||
&[MatrixVersion::V1_0],
|
||||
&self.inner.server_versions,
|
||||
)
|
||||
} else {
|
||||
sso_login::v3::Request::new(redirect_url).try_into_http_request::<Vec<u8>>(
|
||||
homeserver.as_str(),
|
||||
SendAccessToken::None,
|
||||
// FIXME: Use versions reported by server
|
||||
&[MatrixVersion::V1_0],
|
||||
&self.inner.server_versions,
|
||||
)
|
||||
};
|
||||
|
||||
@@ -1306,6 +1282,7 @@ impl Client {
|
||||
/// client.public_rooms(limit, since, server).await;
|
||||
/// # });
|
||||
/// ```
|
||||
#[cfg_attr(not(target_arch = "wasm32"), deny(clippy::future_not_send))]
|
||||
pub async fn public_rooms(
|
||||
&self,
|
||||
limit: Option<u32>,
|
||||
@@ -1449,7 +1426,11 @@ impl Client {
|
||||
});
|
||||
|
||||
let request_config = self.inner.http_client.request_config.timeout(timeout);
|
||||
Ok(self.inner.http_client.upload(request, Some(request_config)).await?)
|
||||
Ok(self
|
||||
.inner
|
||||
.http_client
|
||||
.upload(request, Some(request_config), self.inner.server_versions.clone())
|
||||
.await?)
|
||||
}
|
||||
|
||||
/// Send an arbitrary request to the server, without updating client state.
|
||||
@@ -1501,7 +1482,7 @@ impl Client {
|
||||
Request: OutgoingRequest + Debug,
|
||||
HttpError: From<FromHttpResponseError<Request::EndpointError>>,
|
||||
{
|
||||
self.inner.http_client.send(request, config).await
|
||||
self.inner.http_client.send(request, config, self.inner.server_versions.clone()).await
|
||||
}
|
||||
|
||||
/// Get information of all our own devices.
|
||||
@@ -2261,6 +2242,7 @@ pub(crate) mod test {
|
||||
uiaa::{self, UiaaResponse},
|
||||
},
|
||||
error::{FromHttpResponseError, ServerError},
|
||||
MatrixVersion,
|
||||
},
|
||||
assign, device_id,
|
||||
directory::Filter,
|
||||
@@ -2289,7 +2271,7 @@ pub(crate) mod test {
|
||||
|
||||
fn test_client_builder() -> ClientBuilder {
|
||||
let homeserver = Url::parse(&mockito::server_url()).unwrap();
|
||||
Client::builder().homeserver_url(homeserver).check_supported_versions(false)
|
||||
Client::builder().homeserver_url(homeserver).server_versions([MatrixVersion::V1_0])
|
||||
}
|
||||
|
||||
async fn no_retry_test_client() -> Client {
|
||||
|
||||
@@ -113,6 +113,7 @@ impl HttpClient {
|
||||
request: Request,
|
||||
session: Arc<RwLock<Option<Session>>>,
|
||||
config: Option<RequestConfig>,
|
||||
server_versions: Arc<[MatrixVersion]>,
|
||||
) -> Result<http::Response<Bytes>, HttpError> {
|
||||
let config = match config {
|
||||
Some(config) => config,
|
||||
@@ -148,8 +149,7 @@ impl HttpClient {
|
||||
request.try_into_http_request::<BytesMut>(
|
||||
&self.homeserver.read().await.to_string(),
|
||||
send_access_token,
|
||||
// FIXME: Use versions reported by server
|
||||
&[MatrixVersion::V1_0],
|
||||
&server_versions,
|
||||
)?
|
||||
} else {
|
||||
let (send_access_token, user_id) = {
|
||||
@@ -164,8 +164,7 @@ impl HttpClient {
|
||||
&self.homeserver.read().await.to_string(),
|
||||
send_access_token,
|
||||
&user_id,
|
||||
// FIXME: Use versions reported by server
|
||||
&[MatrixVersion::V1_0],
|
||||
&server_versions,
|
||||
)?
|
||||
};
|
||||
|
||||
@@ -177,8 +176,10 @@ impl HttpClient {
|
||||
&self,
|
||||
request: create_content::v3::Request<'_>,
|
||||
config: Option<RequestConfig>,
|
||||
server_versions: Arc<[MatrixVersion]>,
|
||||
) -> Result<create_content::v3::Response, HttpError> {
|
||||
let response = self.send_request(request, self.session.clone(), config).await?;
|
||||
let response =
|
||||
self.send_request(request, self.session.clone(), config, server_versions).await?;
|
||||
Ok(create_content::v3::Response::try_from_http_response(response)?)
|
||||
}
|
||||
|
||||
@@ -186,12 +187,14 @@ impl HttpClient {
|
||||
&self,
|
||||
request: Request,
|
||||
config: Option<RequestConfig>,
|
||||
server_versions: Arc<[MatrixVersion]>,
|
||||
) -> Result<Request::IncomingResponse, HttpError>
|
||||
where
|
||||
Request: OutgoingRequest + Debug,
|
||||
HttpError: From<FromHttpResponseError<Request::EndpointError>>,
|
||||
{
|
||||
let response = self.send_request(request, self.session.clone(), config).await?;
|
||||
let response =
|
||||
self.send_request(request, self.session.clone(), config, server_versions).await?;
|
||||
|
||||
trace!("Got response: {:?}", response);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user