From 6585aeb628d7701c36226ffd629679528a669249 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Tue, 13 Apr 2021 13:15:57 +0200 Subject: [PATCH] api: Make OutgoingResponse a supertrait of EndpointError --- ruma-api-macros/src/api/response/incoming.rs | 4 ++- ruma-api/src/error.rs | 10 ++++++-- ruma-api/src/lib.rs | 22 ++++++++-------- ruma-api/tests/manual_endpoint_impl.rs | 2 +- ruma-client-api/src/error.rs | 17 +++++++----- ruma-client-api/src/r0/uiaa.rs | 27 +++++++++++--------- 6 files changed, 48 insertions(+), 34 deletions(-) diff --git a/ruma-api-macros/src/api/response/incoming.rs b/ruma-api-macros/src/api/response/incoming.rs index 7e356935..c11c9f57 100644 --- a/ruma-api-macros/src/api/response/incoming.rs +++ b/ruma-api-macros/src/api/response/incoming.rs @@ -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()) diff --git a/ruma-api/src/error.rs b/ruma-api/src/error.rs index 1ce59d31..8b8cc13e 100644 --- a/ruma-api/src/error.rs +++ b/ruma-api/src/error.rs @@ -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>, IntoHttpError> { + match self {} + } +} + impl EndpointError for Void { - fn try_from_response( + fn try_from_http_response( _response: http::Response, ) -> Result { Err(ResponseDeserializationError::none()) diff --git a/ruma-api/src/lib.rs b/ruma-api/src/lib.rs index a5e2547d..02e3890e 100644 --- a/ruma-api/src/lib.rs +++ b/ruma-api/src/lib.rs @@ -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( - response: http::Response, - ) -> Result; -} - /// 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>, 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( + response: http::Response, + ) -> Result; +} + /// Marker trait for requests that don't require authentication, for the client side. pub trait OutgoingNonAuthRequest: OutgoingRequest {} diff --git a/ruma-api/tests/manual_endpoint_impl.rs b/ruma-api/tests/manual_endpoint_impl.rs index 9de917b6..d28b9e63 100644 --- a/ruma-api/tests/manual_endpoint_impl.rs +++ b/ruma-api/tests/manual_endpoint_impl.rs @@ -107,7 +107,7 @@ impl IncomingResponse for Response { Ok(Response) } else { Err(FromHttpResponseError::Http(ServerError::Known( - ::try_from_response(http_response)?, + ::try_from_http_response(http_response)?, ))) } } diff --git a/ruma-client-api/src/error.rs b/ruma-client-api/src/error.rs index 0fe74627..b1b8996f 100644 --- a/ruma-client-api/src/error.rs +++ b/ruma-client-api/src/error.rs @@ -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( + fn try_from_http_response( response: http::Response, ) -> Result { let status = response.status(); @@ -233,13 +236,13 @@ impl ErrorBody { } } -impl From for http::Response> { - fn from(error: Error) -> http::Response> { +impl OutgoingResponse for Error { + fn try_into_http_response(self) -> Result>, 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) } } diff --git a/ruma-client-api/src/r0/uiaa.rs b/ruma-client-api/src/r0/uiaa.rs index fc8ba0bd..9b4aa400 100644 --- a/ruma-client-api/src/r0/uiaa.rs +++ b/ruma-client-api/src/r0/uiaa.rs @@ -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 for UiaaResponse { } impl EndpointError for UiaaResponse { - fn try_from_response( + fn try_from_http_response( response: http::Response, ) -> Result { 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 for http::Response> { - fn from(uiaa_response: UiaaResponse) -> http::Response> { - match uiaa_response { +impl OutgoingResponse for UiaaResponse { + fn try_into_http_response(self) -> Result>, 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 for http::Response> { 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> = UiaaResponse::AuthResponse(uiaa_info).into(); + let uiaa_response = UiaaResponse::AuthResponse(uiaa_info).try_into_http_response(); assert_matches!( from_json_slice::(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"), };