Skip to content

Commit

Permalink
sdk: Add ClientBuilder::requires_sliding_sync method.
Browse files Browse the repository at this point in the history
  • Loading branch information
pixlwave authored and poljar committed Jun 20, 2024
1 parent 8bf104c commit 748f40c
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 5 deletions.
21 changes: 16 additions & 5 deletions bindings/matrix-sdk-ffi/src/client_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,25 @@ impl From<qrcode::LoginProgress> for QrLoginProgress {
#[uniffi(flat_error)]
pub enum ClientBuildError {
#[error(transparent)]
Sdk(#[from] MatrixClientBuildError),
Sdk(MatrixClientBuildError),
#[error("The homeserver doesn't provide a trusted sliding sync proxy in its well-known configuration.")]
SlidingSyncNotAvailable,

#[error("Failed to build the client: {message}")]
Generic { message: String },
}

impl From<MatrixClientBuildError> for ClientBuildError {
fn from(e: MatrixClientBuildError) -> Self {
match e {
MatrixClientBuildError::SlidingSyncNotAvailable => {
ClientBuildError::SlidingSyncNotAvailable
}
_ => ClientBuildError::Sdk(e),
}
}
}

impl From<IdParseError> for ClientBuildError {
fn from(e: IdParseError) -> ClientBuildError {
ClientBuildError::Generic { message: format!("{e:#}") }
Expand Down Expand Up @@ -571,6 +582,10 @@ impl ClientBuilder {

inner_builder = inner_builder.with_encryption_settings(builder.encryption_settings);

if builder.requires_sliding_sync {
inner_builder = inner_builder.requires_sliding_sync();
}

let sdk_client = inner_builder.build().await?;

// At this point, `sdk_client` might contain a `sliding_sync_proxy` that has
Expand All @@ -590,10 +605,6 @@ impl ClientBuilder {
sdk_client.set_sliding_sync_proxy(Some(Url::parse(&sliding_sync_proxy)?));
}

if builder.requires_sliding_sync && sdk_client.sliding_sync_proxy().is_none() {
return Err(ClientBuildError::SlidingSyncNotAvailable);
}

Ok(Client::new(sdk_client, builder.cross_process_refresh_lock_id, builder.session_delegate)
.await?)
}
Expand Down
97 changes: 97 additions & 0 deletions crates/matrix-sdk/src/client/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ use crate::{
pub struct ClientBuilder {
homeserver_cfg: Option<HomeserverConfig>,
#[cfg(feature = "experimental-sliding-sync")]
requires_sliding_sync: bool,
#[cfg(feature = "experimental-sliding-sync")]
sliding_sync_proxy: Option<String>,
http_cfg: Option<HttpConfig>,
store_config: BuilderStoreConfig,
Expand All @@ -101,6 +103,8 @@ impl ClientBuilder {
Self {
homeserver_cfg: None,
#[cfg(feature = "experimental-sliding-sync")]
requires_sliding_sync: false,
#[cfg(feature = "experimental-sliding-sync")]
sliding_sync_proxy: None,
http_cfg: None,
store_config: BuilderStoreConfig::Custom(StoreConfig::default()),
Expand All @@ -127,6 +131,18 @@ impl ClientBuilder {
self
}

/// Ensures that the client is built with support for sliding-sync, either
/// by discovering a proxy through the homeserver's well-known or by
/// providing one through [`Self::sliding_sync_proxy`].
///
/// In the future this may also perform a check for native support on the
/// homeserver.
#[cfg(feature = "experimental-sliding-sync")]
pub fn requires_sliding_sync(mut self) -> Self {
self.requires_sliding_sync = true;
self
}

/// Set the sliding-sync proxy URL to use.
///
/// This value is always used no matter if the homeserver URL was defined
Expand Down Expand Up @@ -439,6 +455,12 @@ impl ClientBuilder {
}
}

#[cfg(feature = "experimental-sliding-sync")]
if self.requires_sliding_sync && sliding_sync_proxy.is_none() {
// In the future we will need to check for native support on the homeserver too.
return Err(ClientBuildError::SlidingSyncNotAvailable);
}

let homeserver = Url::parse(&homeserver)?;

let auth_ctx = Arc::new(AuthCtx {
Expand Down Expand Up @@ -746,6 +768,10 @@ pub enum ClientBuildError {
#[error("Error looking up the .well-known endpoint on auto-discovery")]
AutoDiscovery(FromHttpResponseError<RumaApiError>),

/// The builder requires support for sliding sync but it isn't available.
#[error("The homeserver doesn't support sliding sync and a custom proxy wasn't configured.")]
SlidingSyncNotAvailable,

/// An error encountered when trying to parse the homeserver url.
#[error(transparent)]
Url(#[from] url::ParseError),
Expand Down Expand Up @@ -1002,6 +1028,77 @@ pub(crate) mod tests {
assert_eq!(client.sliding_sync_proxy(), Some("https://localhost:9012".parse().unwrap()));
}

/* Requires sliding sync */

#[async_test]
#[cfg(feature = "experimental-sliding-sync")]
async fn test_requires_sliding_sync_with_legacy_well_known() {
// Given a base server with a well-known file that points to a homeserver that
// doesn't support sliding sync.
let server = MockServer::start().await;
let homeserver = make_mock_homeserver().await;
let mut builder = ClientBuilder::new();

Mock::given(method("GET"))
.and(path("/.well-known/matrix/client"))
.respond_with(
ResponseTemplate::new(200)
.set_body_json(make_well_known_json(&homeserver.uri(), None)),
)
.mount(&server)
.await;

// When building a client that requires sliding sync with the base server.
builder = builder.requires_sliding_sync().server_name_or_homeserver_url(server.uri());
let error = builder.build().await.unwrap_err();

// Then the operation should fail due to the lack of sliding sync support.
assert_matches!(error, ClientBuildError::SlidingSyncNotAvailable);
}

#[async_test]
#[cfg(feature = "experimental-sliding-sync")]
async fn test_requires_sliding_sync_with_well_known() {
// Given a base server with a well-known file that points to a homeserver with a
// sliding sync proxy.
let server = MockServer::start().await;
let homeserver = make_mock_homeserver().await;
let mut builder = ClientBuilder::new();

Mock::given(method("GET"))
.and(path("/.well-known/matrix/client"))
.respond_with(ResponseTemplate::new(200).set_body_json(make_well_known_json(
&homeserver.uri(),
Some("https://localhost:1234"),
)))
.mount(&server)
.await;

// When building a client that requires sliding sync with the base server.
builder = builder.requires_sliding_sync().server_name_or_homeserver_url(server.uri());
let _client = builder.build().await.unwrap();

// Then a client should be built with support for sliding sync.
assert_eq!(_client.sliding_sync_proxy(), Some("https://localhost:1234".parse().unwrap()));
}

#[async_test]
#[cfg(feature = "experimental-sliding-sync")]
async fn test_requires_sliding_sync_with_custom_proxy() {
// Given a homeserver without a well-known file and with a custom sliding sync
// proxy injected.
let homeserver = make_mock_homeserver().await;
let mut builder = ClientBuilder::new();
builder = builder.sliding_sync_proxy("https://localhost:1234");

// When building a client that requires sliding sync with the server's URL.
builder = builder.requires_sliding_sync().server_name_or_homeserver_url(homeserver.uri());
let _client = builder.build().await.unwrap();

// Then a client should be built with support for sliding sync.
assert_eq!(_client.sliding_sync_proxy(), Some("https://localhost:1234".parse().unwrap()));
}

/* Helper functions */

async fn make_mock_homeserver() -> MockServer {
Expand Down

0 comments on commit 748f40c

Please sign in to comment.