refactor(sdk): Don't require the whole session for sending

Allow to send requests when only the access token is available.

Remove the unreachable UserIdRequired error.
This commit is contained in:
Kévin Commaille
2022-08-04 19:40:36 +02:00
committed by Damir Jelić
parent e788ec6b07
commit 52e70f1955
4 changed files with 62 additions and 39 deletions

View File

@@ -394,6 +394,7 @@ impl ClientBuilder {
Some(RequestConfig::short_retry()),
homeserver,
None,
None,
&[MatrixVersion::V1_0],
)
.await

View File

@@ -344,6 +344,31 @@ impl Client {
self.base_client().session_tokens().get_cloned()
}
/// Get the current access token for this session.
///
/// Will be `None` if the client has not been logged in.
///
/// After login, this token should only change if support for [refreshing
/// access tokens] has been enabled.
///
/// [refreshing access tokens]: https://spec.matrix.org/v1.3/client-server-api/#refreshing-access-tokens
pub fn access_token(&self) -> Option<String> {
self.session_tokens().map(|tokens| tokens.access_token)
}
/// Get the current refresh token for this session.
///
/// Will be `None` if the client has not been logged in, or if the access
/// token doesn't expire.
///
/// After login, this token should only change if support for [refreshing
/// access tokens] has been enabled.
///
/// [refreshing access tokens]: https://spec.matrix.org/v1.3/client-server-api/#refreshing-access-tokens
pub fn refresh_token(&self) -> Option<String> {
self.session_tokens().and_then(|tokens| tokens.refresh_token)
}
/// [`Signal`] to get notified when the current access token and optional
/// refresh token for this session change.
///
@@ -1339,11 +1364,8 @@ impl Client {
/// persist_session(client.session());
///
/// // Handle when an `M_UNKNOWN_TOKEN` error is encountered.
/// async fn on_unknown_token_err(
/// client: &Client,
/// session: &Session,
/// ) -> Result<(), Error> {
/// if session.refresh_token.is_some()
/// async fn on_unknown_token_err(client: &Client) -> Result<(), Error> {
/// if client.refresh_token().is_some()
/// && client.refresh_access_token().await.is_ok()
/// {
/// persist_session(client.session());
@@ -1397,7 +1419,8 @@ impl Client {
request,
None,
self.homeserver().await.to_string(),
self.session().as_ref(),
self.access_token().as_deref(),
self.user_id(),
self.server_versions().await?,
)
.await;
@@ -1764,7 +1787,8 @@ impl Client {
request,
Some(request_config),
self.homeserver().await.to_string(),
self.session().as_ref(),
self.access_token().as_deref(),
self.user_id(),
self.server_versions().await?,
)
.await?)
@@ -1865,7 +1889,8 @@ impl Client {
request,
config,
self.homeserver().await.to_string(),
self.session().as_ref(),
self.access_token().as_deref(),
self.user_id(),
self.server_versions().await?,
)
.await
@@ -1880,6 +1905,7 @@ impl Client {
None,
self.homeserver().await.to_string(),
None,
None,
&[MatrixVersion::V1_0],
)
.await?

View File

@@ -98,10 +98,6 @@ pub enum HttpError {
#[error("The request cannot be cloned")]
UnableToCloneRequest,
/// Tried to send a request without `user_id` in the `Session`
#[error("missing user_id in session")]
UserIdRequired,
/// An error occurred while refreshing the access token.
#[error(transparent)]
RefreshToken(#[from] RefreshTokenError),

View File

@@ -19,13 +19,16 @@ use bytes::{Bytes, BytesMut};
use http::Response as HttpResponse;
use matrix_sdk_common::AsyncTraitDeps;
use reqwest::Response;
use ruma::api::{
error::FromHttpResponseError, AuthScheme, IncomingResponse, MatrixVersion, OutgoingRequest,
OutgoingRequestAppserviceExt, SendAccessToken,
use ruma::{
api::{
error::FromHttpResponseError, AuthScheme, IncomingResponse, MatrixVersion, OutgoingRequest,
OutgoingRequestAppserviceExt, SendAccessToken,
},
UserId,
};
use tracing::trace;
use crate::{config::RequestConfig, error::HttpError, Session};
use crate::{config::RequestConfig, error::HttpError};
pub(crate) const DEFAULT_REQUEST_TIMEOUT: Duration = Duration::from_secs(10);
@@ -108,7 +111,8 @@ impl HttpClient {
request: Request,
config: Option<RequestConfig>,
homeserver: String,
session: Option<&Session>,
access_token: Option<&str>,
user_id: Option<&UserId>,
server_versions: &[MatrixVersion],
) -> Result<Request::IncomingResponse, HttpError>
where
@@ -126,23 +130,26 @@ impl HttpClient {
}
trace!("Serializing request");
// We can't assert the identity without a session.
let request = if !config.assert_identity || session.is_none() {
let send_access_token = if auth_scheme == AuthScheme::None && !config.force_auth {
// Small optimization: Don't take the session lock if we know the auth token
// isn't going to be used anyways.
SendAccessToken::None
} else {
match session {
Some(sess) => {
if config.force_auth {
SendAccessToken::Always(&sess.access_token)
} else {
SendAccessToken::IfRequired(&sess.access_token)
}
// We can't assert the identity without a user_id.
let request = if let Some((access_token, user_id)) =
access_token.filter(|_| config.assert_identity).zip(user_id)
{
request.try_into_http_request_with_user_id::<BytesMut>(
&homeserver,
SendAccessToken::Always(access_token),
user_id,
server_versions,
)?
} else {
let send_access_token = match access_token {
Some(access_token) => {
if config.force_auth {
SendAccessToken::Always(access_token)
} else {
SendAccessToken::IfRequired(access_token)
}
None => SendAccessToken::None,
}
None => SendAccessToken::None,
};
request.try_into_http_request::<BytesMut>(
@@ -150,13 +157,6 @@ impl HttpClient {
send_access_token,
server_versions,
)?
} else {
request.try_into_http_request_with_user_id::<BytesMut>(
&homeserver,
SendAccessToken::Always(&session.ok_or(HttpError::UserIdRequired)?.access_token),
&session.ok_or(HttpError::UserIdRequired)?.user_id,
server_versions,
)?
};
let request = request.map(|body| body.freeze());