fix(sdk): Use a pure HTTP error for methods that don't touch local state
This commit is contained in:
parent
afc8597d3b
commit
6e4a57046e
7 changed files with 65 additions and 34 deletions
|
@ -145,7 +145,7 @@ use crate::{
|
||||||
verification::{QrVerification, SasVerification, Verification, VerificationRequest},
|
verification::{QrVerification, SasVerification, Verification, VerificationRequest},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
error::HttpError,
|
error::{HttpError, HttpResult},
|
||||||
event_handler::{EventHandler, EventHandlerData, EventHandlerResult, EventKind, SyncEvent},
|
event_handler::{EventHandler, EventHandlerData, EventHandlerResult, EventKind, SyncEvent},
|
||||||
http_client::{client_with_config, HttpClient, HttpSend},
|
http_client::{client_with_config, HttpClient, HttpSend},
|
||||||
room, Error, Result,
|
room, Error, Result,
|
||||||
|
@ -645,7 +645,7 @@ impl Client {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn discover_homeserver(&self) -> Result<discover_homeserver::Response> {
|
async fn discover_homeserver(&self) -> HttpResult<discover_homeserver::Response> {
|
||||||
self.send(discover_homeserver::Request::new(), Some(RequestConfig::new().disable_retry()))
|
self.send(discover_homeserver::Request::new(), Some(RequestConfig::new().disable_retry()))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -660,7 +660,7 @@ impl Client {
|
||||||
*homeserver = homeserver_url;
|
*homeserver = homeserver_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_supported_versions(&self) -> Result<get_supported_versions::Response> {
|
async fn get_supported_versions(&self) -> HttpResult<get_supported_versions::Response> {
|
||||||
self.send(
|
self.send(
|
||||||
get_supported_versions::Request::new(),
|
get_supported_versions::Request::new(),
|
||||||
Some(RequestConfig::new().disable_retry()),
|
Some(RequestConfig::new().disable_retry()),
|
||||||
|
@ -1123,7 +1123,7 @@ impl Client {
|
||||||
///
|
///
|
||||||
/// This should be the first step when trying to login so you can call the
|
/// This should be the first step when trying to login so you can call the
|
||||||
/// appropriate method for the next step.
|
/// appropriate method for the next step.
|
||||||
pub async fn get_login_types(&self) -> Result<get_login_types::Response> {
|
pub async fn get_login_types(&self) -> HttpResult<get_login_types::Response> {
|
||||||
let request = get_login_types::Request::new();
|
let request = get_login_types::Request::new();
|
||||||
self.send(request, None).await
|
self.send(request, None).await
|
||||||
}
|
}
|
||||||
|
@ -1540,7 +1540,7 @@ impl Client {
|
||||||
pub async fn register(
|
pub async fn register(
|
||||||
&self,
|
&self,
|
||||||
registration: impl Into<register::Request<'_>>,
|
registration: impl Into<register::Request<'_>>,
|
||||||
) -> Result<register::Response> {
|
) -> HttpResult<register::Response> {
|
||||||
info!("Registering to {}", self.homeserver().await);
|
info!("Registering to {}", self.homeserver().await);
|
||||||
|
|
||||||
let config = if self.appservice_mode {
|
let config = if self.appservice_mode {
|
||||||
|
@ -1630,7 +1630,7 @@ impl Client {
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `room_id` - The `RoomId` of the room to be joined.
|
/// * `room_id` - The `RoomId` of the room to be joined.
|
||||||
pub async fn join_room_by_id(&self, room_id: &RoomId) -> Result<join_room_by_id::Response> {
|
pub async fn join_room_by_id(&self, room_id: &RoomId) -> HttpResult<join_room_by_id::Response> {
|
||||||
let request = join_room_by_id::Request::new(room_id);
|
let request = join_room_by_id::Request::new(room_id);
|
||||||
self.send(request, None).await
|
self.send(request, None).await
|
||||||
}
|
}
|
||||||
|
@ -1648,7 +1648,7 @@ impl Client {
|
||||||
&self,
|
&self,
|
||||||
alias: &RoomIdOrAliasId,
|
alias: &RoomIdOrAliasId,
|
||||||
server_names: &[Box<ServerName>],
|
server_names: &[Box<ServerName>],
|
||||||
) -> Result<join_room_by_id_or_alias::Response> {
|
) -> HttpResult<join_room_by_id_or_alias::Response> {
|
||||||
let request = assign!(join_room_by_id_or_alias::Request::new(alias), {
|
let request = assign!(join_room_by_id_or_alias::Request::new(alias), {
|
||||||
server_name: server_names,
|
server_name: server_names,
|
||||||
});
|
});
|
||||||
|
@ -1691,7 +1691,7 @@ impl Client {
|
||||||
limit: Option<u32>,
|
limit: Option<u32>,
|
||||||
since: Option<&str>,
|
since: Option<&str>,
|
||||||
server: Option<&ServerName>,
|
server: Option<&ServerName>,
|
||||||
) -> Result<get_public_rooms::Response> {
|
) -> HttpResult<get_public_rooms::Response> {
|
||||||
let limit = limit.map(UInt::from);
|
let limit = limit.map(UInt::from);
|
||||||
|
|
||||||
let request = assign!(get_public_rooms::Request::new(), {
|
let request = assign!(get_public_rooms::Request::new(), {
|
||||||
|
@ -1732,7 +1732,7 @@ impl Client {
|
||||||
pub async fn create_room(
|
pub async fn create_room(
|
||||||
&self,
|
&self,
|
||||||
room: impl Into<create_room::Request<'_>>,
|
room: impl Into<create_room::Request<'_>>,
|
||||||
) -> Result<create_room::Response> {
|
) -> HttpResult<create_room::Response> {
|
||||||
let request = room.into();
|
let request = room.into();
|
||||||
self.send(request, None).await
|
self.send(request, None).await
|
||||||
}
|
}
|
||||||
|
@ -1772,7 +1772,7 @@ impl Client {
|
||||||
pub async fn public_rooms_filtered(
|
pub async fn public_rooms_filtered(
|
||||||
&self,
|
&self,
|
||||||
room_search: impl Into<get_public_rooms_filtered::Request<'_>>,
|
room_search: impl Into<get_public_rooms_filtered::Request<'_>>,
|
||||||
) -> Result<get_public_rooms_filtered::Response> {
|
) -> HttpResult<get_public_rooms_filtered::Response> {
|
||||||
let request = room_search.into();
|
let request = room_search.into();
|
||||||
self.send(request, None).await
|
self.send(request, None).await
|
||||||
}
|
}
|
||||||
|
@ -1906,7 +1906,7 @@ impl Client {
|
||||||
let txn_id = txn_id.unwrap_or_else(Uuid::new_v4).to_string();
|
let txn_id = txn_id.unwrap_or_else(Uuid::new_v4).to_string();
|
||||||
let request = send_message_event::Request::new(room_id, &txn_id, &content);
|
let request = send_message_event::Request::new(room_id, &txn_id, &content);
|
||||||
|
|
||||||
self.send(request, None).await
|
Ok(self.send(request, None).await?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1954,7 +1954,7 @@ impl Client {
|
||||||
&self,
|
&self,
|
||||||
request: Request,
|
request: Request,
|
||||||
config: Option<RequestConfig>,
|
config: Option<RequestConfig>,
|
||||||
) -> Result<Request::IncomingResponse>
|
) -> HttpResult<Request::IncomingResponse>
|
||||||
where
|
where
|
||||||
Request: OutgoingRequest + Debug,
|
Request: OutgoingRequest + Debug,
|
||||||
HttpError: From<FromHttpResponseError<Request::EndpointError>>,
|
HttpError: From<FromHttpResponseError<Request::EndpointError>>,
|
||||||
|
@ -1966,8 +1966,9 @@ impl Client {
|
||||||
pub(crate) async fn send_to_device(
|
pub(crate) async fn send_to_device(
|
||||||
&self,
|
&self,
|
||||||
request: &ToDeviceRequest,
|
request: &ToDeviceRequest,
|
||||||
) -> Result<ToDeviceResponse> {
|
) -> HttpResult<ToDeviceResponse> {
|
||||||
let txn_id_string = request.txn_id_string();
|
let txn_id_string = request.txn_id_string();
|
||||||
|
|
||||||
let request = RumaToDeviceRequest::new_raw(
|
let request = RumaToDeviceRequest::new_raw(
|
||||||
request.event_type.as_str(),
|
request.event_type.as_str(),
|
||||||
&txn_id_string,
|
&txn_id_string,
|
||||||
|
@ -2000,7 +2001,7 @@ impl Client {
|
||||||
/// }
|
/// }
|
||||||
/// # });
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn devices(&self) -> Result<get_devices::Response> {
|
pub async fn devices(&self) -> HttpResult<get_devices::Response> {
|
||||||
let request = get_devices::Request::new();
|
let request = get_devices::Request::new();
|
||||||
|
|
||||||
self.send(request, None).await
|
self.send(request, None).await
|
||||||
|
@ -2057,7 +2058,7 @@ impl Client {
|
||||||
&self,
|
&self,
|
||||||
devices: &[DeviceIdBox],
|
devices: &[DeviceIdBox],
|
||||||
auth_data: Option<AuthData<'_>>,
|
auth_data: Option<AuthData<'_>>,
|
||||||
) -> Result<delete_devices::Response> {
|
) -> HttpResult<delete_devices::Response> {
|
||||||
let mut request = delete_devices::Request::new(devices);
|
let mut request = delete_devices::Request::new(devices);
|
||||||
request.auth = auth_data;
|
request.auth = auth_data;
|
||||||
|
|
||||||
|
@ -2965,7 +2966,7 @@ impl Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets information about the owner of a given access token.
|
/// Gets information about the owner of a given access token.
|
||||||
pub async fn whoami(&self) -> Result<whoami::Response> {
|
pub async fn whoami(&self) -> HttpResult<whoami::Response> {
|
||||||
let request = whoami::Request::new();
|
let request = whoami::Request::new();
|
||||||
self.send(request, None).await
|
self.send(request, None).await
|
||||||
}
|
}
|
||||||
|
@ -3414,12 +3415,8 @@ mod test {
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Err(err) = client.register(user).await {
|
if let Err(err) = client.register(user).await {
|
||||||
if let crate::Error::Http(HttpError::UiaaError(FromHttpResponseError::Http(
|
if let HttpError::UiaaError(FromHttpResponseError::Http(ServerError::Known(
|
||||||
ServerError::Known(UiaaResponse::MatrixError(client_api::Error {
|
UiaaResponse::MatrixError(client_api::Error { kind, message, status_code }),
|
||||||
kind,
|
|
||||||
message,
|
|
||||||
status_code,
|
|
||||||
})),
|
|
||||||
))) = err
|
))) = err
|
||||||
{
|
{
|
||||||
if let client_api::error::ErrorKind::Forbidden = kind {
|
if let client_api::error::ErrorKind::Forbidden = kind {
|
||||||
|
|
|
@ -40,6 +40,9 @@ use url::ParseError as UrlParseError;
|
||||||
/// Result type of the rust-sdk.
|
/// Result type of the rust-sdk.
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
|
/// Result type of a pure HTTP request.
|
||||||
|
pub type HttpResult<T> = std::result::Result<T, HttpError>;
|
||||||
|
|
||||||
/// An HTTP error, representing either a connection error or an error while
|
/// An HTTP error, representing either a connection error or an error while
|
||||||
/// converting the raw HTTP response into a Matrix response.
|
/// converting the raw HTTP response into a Matrix response.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
@ -182,6 +185,30 @@ pub enum RoomKeyImportError {
|
||||||
Export(#[from] KeyExportError),
|
Export(#[from] KeyExportError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HttpError {
|
||||||
|
/// Try to destructure the error into an universal interactive auth info.
|
||||||
|
///
|
||||||
|
/// Some requests require universal interactive auth, doing such a request
|
||||||
|
/// will always fail the first time with a 401 status code, the response
|
||||||
|
/// body will contain info how the client can authenticate.
|
||||||
|
///
|
||||||
|
/// The request will need to be retried, this time containing additional
|
||||||
|
/// authentication data.
|
||||||
|
///
|
||||||
|
/// This method is an convenience method to get to the info the server
|
||||||
|
/// returned on the first, failed request.
|
||||||
|
pub fn uiaa_response(&self) -> Option<&UiaaInfo> {
|
||||||
|
if let HttpError::UiaaError(FromHttpResponseError::Http(ServerError::Known(
|
||||||
|
UiaaError::AuthResponse(i),
|
||||||
|
))) = self
|
||||||
|
{
|
||||||
|
Some(i)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
/// Try to destructure the error into an universal interactive auth info.
|
/// Try to destructure the error into an universal interactive auth info.
|
||||||
///
|
///
|
||||||
|
|
|
@ -107,7 +107,7 @@ pub use client::{Client, ClientConfig, LoopCtrl, RequestConfig, SyncSettings};
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
#[cfg_attr(feature = "docs", doc(cfg(encryption)))]
|
#[cfg_attr(feature = "docs", doc(cfg(encryption)))]
|
||||||
pub use device::Device;
|
pub use device::Device;
|
||||||
pub use error::{Error, HttpError, Result};
|
pub use error::{Error, HttpError, HttpResult, Result};
|
||||||
pub use http_client::HttpSend;
|
pub use http_client::HttpSend;
|
||||||
pub use room_member::RoomMember;
|
pub use room_member::RoomMember;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
|
|
@ -14,6 +14,7 @@ use ruma::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
error::HttpResult,
|
||||||
media::{MediaFormat, MediaRequest, MediaType},
|
media::{MediaFormat, MediaRequest, MediaType},
|
||||||
room::RoomType,
|
room::RoomType,
|
||||||
BaseRoom, Client, Result, RoomMember,
|
BaseRoom, Client, Result, RoomMember,
|
||||||
|
@ -143,7 +144,7 @@ impl Common {
|
||||||
pub async fn messages(
|
pub async fn messages(
|
||||||
&self,
|
&self,
|
||||||
request: impl Into<get_message_events::Request<'_>>,
|
request: impl Into<get_message_events::Request<'_>>,
|
||||||
) -> Result<get_message_events::Response> {
|
) -> HttpResult<get_message_events::Response> {
|
||||||
let request = request.into();
|
let request = request.into();
|
||||||
self.client.send(request, None).await
|
self.client.send(request, None).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ use ruma::{
|
||||||
#[cfg(feature = "encryption")]
|
#[cfg(feature = "encryption")]
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
use crate::{room::Common, BaseRoom, Client, Error, Result, RoomType};
|
use crate::{error::HttpResult, room::Common, BaseRoom, Client, HttpError, Result, RoomType};
|
||||||
|
|
||||||
const TYPING_NOTICE_TIMEOUT: Duration = Duration::from_secs(4);
|
const TYPING_NOTICE_TIMEOUT: Duration = Duration::from_secs(4);
|
||||||
const TYPING_NOTICE_RESEND_TIMEOUT: Duration = Duration::from_secs(3);
|
const TYPING_NOTICE_RESEND_TIMEOUT: Duration = Duration::from_secs(3);
|
||||||
|
@ -562,7 +562,7 @@ impl Joined {
|
||||||
&self,
|
&self,
|
||||||
content: impl Into<AnyStateEventContent>,
|
content: impl Into<AnyStateEventContent>,
|
||||||
state_key: &str,
|
state_key: &str,
|
||||||
) -> Result<send_state_event::Response> {
|
) -> HttpResult<send_state_event::Response> {
|
||||||
let content = content.into();
|
let content = content.into();
|
||||||
let request = send_state_event::Request::new(self.inner.room_id(), state_key, &content);
|
let request = send_state_event::Request::new(self.inner.room_id(), state_key, &content);
|
||||||
|
|
||||||
|
@ -606,7 +606,7 @@ impl Joined {
|
||||||
event_id: &EventId,
|
event_id: &EventId,
|
||||||
reason: Option<&str>,
|
reason: Option<&str>,
|
||||||
txn_id: Option<Uuid>,
|
txn_id: Option<Uuid>,
|
||||||
) -> Result<redact_event::Response> {
|
) -> HttpResult<redact_event::Response> {
|
||||||
let txn_id = txn_id.unwrap_or_else(Uuid::new_v4).to_string();
|
let txn_id = txn_id.unwrap_or_else(Uuid::new_v4).to_string();
|
||||||
let request =
|
let request =
|
||||||
assign!(redact_event::Request::new(self.inner.room_id(), event_id, &txn_id), {
|
assign!(redact_event::Request::new(self.inner.room_id(), event_id, &txn_id), {
|
||||||
|
@ -642,8 +642,8 @@ impl Joined {
|
||||||
/// room.set_tag("u.work", tag_info );
|
/// room.set_tag("u.work", tag_info );
|
||||||
/// # })
|
/// # })
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn set_tag(&self, tag: &str, tag_info: TagInfo) -> Result<create_tag::Response> {
|
pub async fn set_tag(&self, tag: &str, tag_info: TagInfo) -> HttpResult<create_tag::Response> {
|
||||||
let user_id = self.client.user_id().await.ok_or(Error::AuthenticationRequired)?;
|
let user_id = self.client.user_id().await.ok_or(HttpError::AuthenticationRequired)?;
|
||||||
let request = create_tag::Request::new(&user_id, self.inner.room_id(), tag, tag_info);
|
let request = create_tag::Request::new(&user_id, self.inner.room_id(), tag, tag_info);
|
||||||
self.client.send(request, None).await
|
self.client.send(request, None).await
|
||||||
}
|
}
|
||||||
|
@ -654,8 +654,8 @@ impl Joined {
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `tag` - The tag to remove.
|
/// * `tag` - The tag to remove.
|
||||||
pub async fn remove_tag(&self, tag: &str) -> Result<delete_tag::Response> {
|
pub async fn remove_tag(&self, tag: &str) -> HttpResult<delete_tag::Response> {
|
||||||
let user_id = self.client.user_id().await.ok_or(Error::AuthenticationRequired)?;
|
let user_id = self.client.user_id().await.ok_or(HttpError::AuthenticationRequired)?;
|
||||||
let request = delete_tag::Request::new(&user_id, self.inner.room_id(), tag);
|
let request = delete_tag::Request::new(&user_id, self.inner.room_id(), tag);
|
||||||
self.client.send(request, None).await
|
self.client.send(request, None).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,3 +87,9 @@ impl From<warp::Rejection> for Error {
|
||||||
Self::WarpRejection(format!("{:?}", rejection))
|
Self::WarpRejection(format!("{:?}", rejection))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<matrix_sdk::HttpError> for Error {
|
||||||
|
fn from(e: matrix_sdk::HttpError) -> Self {
|
||||||
|
matrix_sdk::Error::from(e).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ use matrix_sdk::{
|
||||||
bytes::Bytes,
|
bytes::Bytes,
|
||||||
event_handler::{EventHandler, EventHandlerResult, SyncEvent},
|
event_handler::{EventHandler, EventHandlerResult, SyncEvent},
|
||||||
reqwest::Url,
|
reqwest::Url,
|
||||||
Client, ClientConfig, HttpError, Session,
|
Client, ClientConfig, Session,
|
||||||
};
|
};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
|
@ -402,9 +402,9 @@ impl AppService {
|
||||||
match client.register(request).await {
|
match client.register(request).await {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(error) => match error {
|
Err(error) => match error {
|
||||||
matrix_sdk::Error::Http(HttpError::UiaaError(FromHttpResponseError::Http(
|
matrix_sdk::HttpError::UiaaError(FromHttpResponseError::Http(
|
||||||
ServerError::Known(UiaaResponse::MatrixError(ref matrix_error)),
|
ServerError::Known(UiaaResponse::MatrixError(ref matrix_error)),
|
||||||
))) => {
|
)) => {
|
||||||
match matrix_error.kind {
|
match matrix_error.kind {
|
||||||
ErrorKind::UserInUse => {
|
ErrorKind::UserInUse => {
|
||||||
// TODO: persist the fact that we registered that user
|
// TODO: persist the fact that we registered that user
|
||||||
|
|
Loading…
Reference in a new issue