api: Make OutgoingResponse a supertrait of EndpointError
This commit is contained in:
parent
cc2f2a231b
commit
6585aeb628
@ -134,7 +134,9 @@ impl Response {
|
||||
#response_init_fields
|
||||
})
|
||||
} else {
|
||||
match <#error_ty as #ruma_api::EndpointError>::try_from_response(response) {
|
||||
match <#error_ty as #ruma_api::EndpointError>::try_from_http_response(
|
||||
response
|
||||
) {
|
||||
Ok(err) => Err(#ruma_api::error::ServerError::Known(err).into()),
|
||||
Err(response_err) => {
|
||||
Err(#ruma_api::error::ServerError::Unknown(response_err).into())
|
||||
|
@ -7,15 +7,21 @@ use std::{error::Error as StdError, fmt};
|
||||
use bytes::Buf;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::EndpointError;
|
||||
use crate::{EndpointError, OutgoingResponse};
|
||||
|
||||
// FIXME when `!` becomes stable use it
|
||||
/// Default `EndpointError` for `ruma_api!` macro
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Void {}
|
||||
|
||||
impl OutgoingResponse for Void {
|
||||
fn try_into_http_response(self) -> Result<http::Response<Vec<u8>>, IntoHttpError> {
|
||||
match self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl EndpointError for Void {
|
||||
fn try_from_response<T: Buf>(
|
||||
fn try_from_http_response<T: Buf>(
|
||||
_response: http::Response<T>,
|
||||
) -> Result<Self, ResponseDeserializationError> {
|
||||
Err(ResponseDeserializationError::none())
|
||||
|
@ -214,17 +214,6 @@ pub mod exports {
|
||||
|
||||
use error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError};
|
||||
|
||||
/// Gives users the ability to define their own serializable / deserializable errors.
|
||||
pub trait EndpointError: StdError + Sized + 'static {
|
||||
/// Tries to construct `Self` from an `http::Response`.
|
||||
///
|
||||
/// This will always return `Err` variant when no `error` field is defined in
|
||||
/// the `ruma_api` macro.
|
||||
fn try_from_response<T: Buf>(
|
||||
response: http::Response<T>,
|
||||
) -> Result<Self, error::ResponseDeserializationError>;
|
||||
}
|
||||
|
||||
/// A request type for a Matrix API endpoint, used for sending requests.
|
||||
pub trait OutgoingRequest: Sized {
|
||||
/// A type capturing the expected error conditions the server can return.
|
||||
@ -324,6 +313,17 @@ pub trait OutgoingResponse {
|
||||
fn try_into_http_response(self) -> Result<http::Response<Vec<u8>>, IntoHttpError>;
|
||||
}
|
||||
|
||||
/// Gives users the ability to define their own serializable / deserializable errors.
|
||||
pub trait EndpointError: OutgoingResponse + StdError + Sized + 'static {
|
||||
/// Tries to construct `Self` from an `http::Response`.
|
||||
///
|
||||
/// This will always return `Err` variant when no `error` field is defined in
|
||||
/// the `ruma_api` macro.
|
||||
fn try_from_http_response<T: Buf>(
|
||||
response: http::Response<T>,
|
||||
) -> Result<Self, error::ResponseDeserializationError>;
|
||||
}
|
||||
|
||||
/// Marker trait for requests that don't require authentication, for the client side.
|
||||
pub trait OutgoingNonAuthRequest: OutgoingRequest {}
|
||||
|
||||
|
@ -107,7 +107,7 @@ impl IncomingResponse for Response {
|
||||
Ok(Response)
|
||||
} else {
|
||||
Err(FromHttpResponseError::Http(ServerError::Known(
|
||||
<Void as EndpointError>::try_from_response(http_response)?,
|
||||
<Void as EndpointError>::try_from_http_response(http_response)?,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,10 @@
|
||||
use std::{collections::BTreeMap, fmt, time::Duration};
|
||||
|
||||
use bytes::Buf;
|
||||
use ruma_api::{error::ResponseDeserializationError, EndpointError};
|
||||
use ruma_api::{
|
||||
error::{IntoHttpError, ResponseDeserializationError},
|
||||
EndpointError, OutgoingResponse,
|
||||
};
|
||||
use ruma_identifiers::RoomVersionId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{from_reader as from_json_reader, to_vec as to_json_vec, Value as JsonValue};
|
||||
@ -203,7 +206,7 @@ pub struct Error {
|
||||
}
|
||||
|
||||
impl EndpointError for Error {
|
||||
fn try_from_response<T: Buf>(
|
||||
fn try_from_http_response<T: Buf>(
|
||||
response: http::Response<T>,
|
||||
) -> Result<Self, ResponseDeserializationError> {
|
||||
let status = response.status();
|
||||
@ -233,13 +236,13 @@ impl ErrorBody {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for http::Response<Vec<u8>> {
|
||||
fn from(error: Error) -> http::Response<Vec<u8>> {
|
||||
impl OutgoingResponse for Error {
|
||||
fn try_into_http_response(self) -> Result<http::Response<Vec<u8>>, IntoHttpError> {
|
||||
http::Response::builder()
|
||||
.header(http::header::CONTENT_TYPE, "application/json")
|
||||
.status(error.status_code)
|
||||
.body(to_json_vec(&ErrorBody::from(error)).unwrap())
|
||||
.unwrap()
|
||||
.status(self.status_code)
|
||||
.body(to_json_vec(&ErrorBody::from(self))?)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,10 @@
|
||||
use std::{collections::BTreeMap, fmt};
|
||||
|
||||
use bytes::Buf;
|
||||
use ruma_api::{error::ResponseDeserializationError, EndpointError};
|
||||
use ruma_api::{
|
||||
error::{IntoHttpError, ResponseDeserializationError},
|
||||
EndpointError, OutgoingResponse,
|
||||
};
|
||||
use ruma_serde::Outgoing;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{
|
||||
@ -134,28 +137,28 @@ impl From<MatrixError> for UiaaResponse {
|
||||
}
|
||||
|
||||
impl EndpointError for UiaaResponse {
|
||||
fn try_from_response<T: Buf>(
|
||||
fn try_from_http_response<T: Buf>(
|
||||
response: http::Response<T>,
|
||||
) -> Result<Self, ResponseDeserializationError> {
|
||||
if response.status() == http::StatusCode::UNAUTHORIZED {
|
||||
Ok(UiaaResponse::AuthResponse(from_json_reader(response.into_body().reader())?))
|
||||
} else {
|
||||
MatrixError::try_from_response(response).map(From::from)
|
||||
MatrixError::try_from_http_response(response).map(From::from)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for UiaaResponse {}
|
||||
|
||||
impl From<UiaaResponse> for http::Response<Vec<u8>> {
|
||||
fn from(uiaa_response: UiaaResponse) -> http::Response<Vec<u8>> {
|
||||
match uiaa_response {
|
||||
impl OutgoingResponse for UiaaResponse {
|
||||
fn try_into_http_response(self) -> Result<http::Response<Vec<u8>>, IntoHttpError> {
|
||||
match self {
|
||||
UiaaResponse::AuthResponse(authentication_info) => http::Response::builder()
|
||||
.header(http::header::CONTENT_TYPE, "application/json")
|
||||
.status(&http::StatusCode::UNAUTHORIZED)
|
||||
.body(to_json_vec(&authentication_info).unwrap())
|
||||
.unwrap(),
|
||||
UiaaResponse::MatrixError(error) => http::Response::from(error),
|
||||
.body(to_json_vec(&authentication_info)?)
|
||||
.map_err(Into::into),
|
||||
UiaaResponse::MatrixError(error) => error.try_into_http_response(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -164,7 +167,7 @@ impl From<UiaaResponse> for http::Response<Vec<u8>> {
|
||||
mod tests {
|
||||
use maplit::btreemap;
|
||||
use matches::assert_matches;
|
||||
use ruma_api::EndpointError;
|
||||
use ruma_api::{EndpointError, OutgoingResponse};
|
||||
use serde_json::{
|
||||
from_slice as from_json_slice, from_str as from_json_str, from_value as from_json_value,
|
||||
json, to_value as to_json_value, value::to_raw_value as to_raw_json_value,
|
||||
@ -334,7 +337,7 @@ mod tests {
|
||||
session: None,
|
||||
auth_error: None,
|
||||
};
|
||||
let uiaa_response: http::Response<Vec<u8>> = UiaaResponse::AuthResponse(uiaa_info).into();
|
||||
let uiaa_response = UiaaResponse::AuthResponse(uiaa_info).try_into_http_response();
|
||||
|
||||
assert_matches!(
|
||||
from_json_slice::<UiaaInfo>(uiaa_response.body()).unwrap(),
|
||||
@ -385,7 +388,7 @@ mod tests {
|
||||
.body(json.as_bytes())
|
||||
.unwrap();
|
||||
|
||||
let parsed_uiaa_info = match UiaaResponse::try_from_response(http_response).unwrap() {
|
||||
let parsed_uiaa_info = match UiaaResponse::try_from_http_response(http_response).unwrap() {
|
||||
UiaaResponse::AuthResponse(uiaa_info) => uiaa_info,
|
||||
_ => panic!("Expected UiaaResponse::AuthResponse"),
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user