From a0f7e1b771d3294187bae0b2816fbcf6ceb40b88 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Sat, 8 May 2021 14:33:12 +0200 Subject: [PATCH] api: Replace error::Void by error::MatrixError --- crates/ruma-api-macros/README.md | 4 +- crates/ruma-api-macros/src/api.rs | 5 +- crates/ruma-api/CHANGELOG.md | 6 +- crates/ruma-api/src/error.rs | 66 ++++++++++--------- crates/ruma-api/src/lib.rs | 2 +- crates/ruma-api/tests/manual_endpoint_impl.rs | 12 ++-- crates/ruma-api/tests/ui/05-request-only.rs | 6 +- .../tests/ui/07-error-type-attribute.rs | 2 +- 8 files changed, 57 insertions(+), 46 deletions(-) diff --git a/crates/ruma-api-macros/README.md b/crates/ruma-api-macros/README.md index fd4c2810..e57de359 100644 --- a/crates/ruma-api-macros/README.md +++ b/crates/ruma-api-macros/README.md @@ -52,8 +52,8 @@ pub mod some_endpoint { pub value: String, } - // An error can also be specified or defaults to `ruma_api::error::Void`. - error: ruma_api::Error + // An error can also be specified or defaults to `ruma_api::error::MatrixError`. + error: crate::Error } } ``` diff --git a/crates/ruma-api-macros/src/api.rs b/crates/ruma-api-macros/src/api.rs index ce703e77..a104b0c1 100644 --- a/crates/ruma-api-macros/src/api.rs +++ b/crates/ruma-api-macros/src/api.rs @@ -63,8 +63,9 @@ pub fn expand_all(api: Api) -> syn::Result { }) .collect(); - let error_ty = - api.error_ty.map_or_else(|| quote! { #ruma_api::error::Void }, |err_ty| quote! { #err_ty }); + let error_ty = api + .error_ty + .map_or_else(|| quote! { #ruma_api::error::MatrixError }, |err_ty| quote! { #err_ty }); let request = api.request.map(|req| req.expand(metadata, &error_ty, &ruma_api)); let response = api.response.map(|res| res.expand(metadata, &error_ty, &ruma_api)); diff --git a/crates/ruma-api/CHANGELOG.md b/crates/ruma-api/CHANGELOG.md index d8e49c0a..7d0b6286 100644 --- a/crates/ruma-api/CHANGELOG.md +++ b/crates/ruma-api/CHANGELOG.md @@ -12,10 +12,14 @@ Breaking changes: * Endpoint authentication is now more granularly defined by an enum `AuthScheme` instead of a boolean. The `ruma_api!` macro has been updated to require `authentication` instead of `requires_authentication`. +* Remove `error::Void`, the default error type for `ruma_api!` is now `error::MatrixError` + (see below) Improvements: -* The `EndpointError`s that come with ruma crates now implement `std::errror::Error`. +* The `EndpointError`s that come with ruma crates now implement `std::errror::Error` +* Add a new `MatrixError` type to the `error` module that consists of a HTTP status code and JSON + `body` and is the new default error type for `ruma_api!` # 0.16.1 diff --git a/crates/ruma-api/src/error.rs b/crates/ruma-api/src/error.rs index d38c9204..c95be91a 100644 --- a/crates/ruma-api/src/error.rs +++ b/crates/ruma-api/src/error.rs @@ -5,39 +5,55 @@ use std::{error::Error as StdError, fmt}; use bytes::BufMut; +use serde_json::{from_slice as from_json_slice, Value as JsonValue}; use thiserror::Error; use crate::{EndpointError, OutgoingResponse}; -// FIXME when `!` becomes stable use it -/// Default `EndpointError` for `ruma_api!` macro -#[derive(Clone, Copy, Debug)] -pub enum Void {} +/// A general-purpose Matrix error type consisting of an HTTP status code and a JSON body. +/// +/// Note that individual `ruma-*-api` crates may provide more specific error types. +#[derive(Clone, Debug)] +pub struct MatrixError { + /// The http reponse's status code. + pub status_code: http::StatusCode, -impl OutgoingResponse for Void { + /// The http response's body. + pub body: JsonValue, +} + +impl fmt::Display for MatrixError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "[{}] ", self.status_code.as_u16())?; + fmt::Display::fmt(&self.body, f) + } +} + +impl StdError for MatrixError {} + +impl OutgoingResponse for MatrixError { fn try_into_http_response( self, ) -> Result, IntoHttpError> { - match self {} + http::Response::builder() + .header(http::header::CONTENT_TYPE, "application/json") + .status(self.status_code) + .body(ruma_serde::json_to_buf(&self.body)?) + .map_err(Into::into) } } -impl EndpointError for Void { +impl EndpointError for MatrixError { fn try_from_http_response>( - _response: http::Response, + response: http::Response, ) -> Result { - Err(ResponseDeserializationError::none()) + Ok(Self { + status_code: response.status(), + body: from_json_slice(response.body().as_ref())?, + }) } } -impl fmt::Display for Void { - fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self {} - } -} - -impl StdError for Void {} - /// An error when converting one of ruma's endpoint-specific request or response /// types to the corresponding http type. #[derive(Debug, Error)] @@ -150,13 +166,7 @@ impl StdError for FromHttpResponseError {} /// An error that occurred when trying to deserialize a response. #[derive(Debug)] pub struct ResponseDeserializationError { - inner: Option, -} - -impl ResponseDeserializationError { - fn none() -> Self { - Self { inner: None } - } + inner: DeserializationError, } impl From for ResponseDeserializationError @@ -164,17 +174,13 @@ where T: Into, { fn from(err: T) -> Self { - Self { inner: Some(err.into()) } + Self { inner: err.into() } } } impl fmt::Display for ResponseDeserializationError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(ref inner) = self.inner { - fmt::Display::fmt(inner, f) - } else { - fmt::Display::fmt("deserialization error, no error specified", f) - } + fmt::Display::fmt(&self.inner, f) } } diff --git a/crates/ruma-api/src/lib.rs b/crates/ruma-api/src/lib.rs index c818bbed..11bd1bbf 100644 --- a/crates/ruma-api/src/lib.rs +++ b/crates/ruma-api/src/lib.rs @@ -49,7 +49,7 @@ use ruma_identifiers::UserId; /// // in the response from this API endpoint. /// } /// -/// // The error returned when a response fails, defaults to `Void`. +/// // The error returned when a response fails, defaults to `MatrixError`. /// error: path::to::Error /// } /// ``` diff --git a/crates/ruma-api/tests/manual_endpoint_impl.rs b/crates/ruma-api/tests/manual_endpoint_impl.rs index 43bf5b84..1e46a199 100644 --- a/crates/ruma-api/tests/manual_endpoint_impl.rs +++ b/crates/ruma-api/tests/manual_endpoint_impl.rs @@ -5,7 +5,7 @@ use std::convert::TryFrom; use bytes::BufMut; use http::{header::CONTENT_TYPE, method::Method}; use ruma_api::{ - error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, ServerError, Void}, + error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, MatrixError, ServerError}, AuthScheme, EndpointError, IncomingRequest, IncomingResponse, Metadata, OutgoingRequest, OutgoingResponse, SendAccessToken, }; @@ -34,7 +34,7 @@ const METADATA: Metadata = Metadata { }; impl OutgoingRequest for Request { - type EndpointError = Void; + type EndpointError = MatrixError; type IncomingResponse = Response; const METADATA: Metadata = METADATA; @@ -62,7 +62,7 @@ impl OutgoingRequest for Request { } impl IncomingRequest for Request { - type EndpointError = Void; + type EndpointError = MatrixError; type OutgoingResponse = Response; const METADATA: Metadata = METADATA; @@ -98,16 +98,16 @@ impl Outgoing for Response { } impl IncomingResponse for Response { - type EndpointError = Void; + type EndpointError = MatrixError; fn try_from_http_response>( http_response: http::Response, - ) -> Result> { + ) -> Result> { if http_response.status().as_u16() < 400 { Ok(Response) } else { Err(FromHttpResponseError::Http(ServerError::Known( - ::try_from_http_response(http_response)?, + ::try_from_http_response(http_response)?, ))) } } diff --git a/crates/ruma-api/tests/ui/05-request-only.rs b/crates/ruma-api/tests/ui/05-request-only.rs index 61579fca..a60fc1aa 100644 --- a/crates/ruma-api/tests/ui/05-request-only.rs +++ b/crates/ruma-api/tests/ui/05-request-only.rs @@ -1,6 +1,6 @@ use bytes::BufMut; use ruma_api::{ - error::{FromHttpResponseError, IntoHttpError, Void}, + error::{FromHttpResponseError, IntoHttpError, MatrixError}, ruma_api, IncomingResponse, OutgoingResponse, }; use ruma_serde::Outgoing; @@ -26,11 +26,11 @@ ruma_api! { pub struct Response; impl IncomingResponse for Response { - type EndpointError = Void; + type EndpointError = MatrixError; fn try_from_http_response>( _: http::Response, - ) -> Result> { + ) -> Result> { todo!() } } diff --git a/crates/ruma-api/tests/ui/07-error-type-attribute.rs b/crates/ruma-api/tests/ui/07-error-type-attribute.rs index b60be7ca..f14f7fc3 100644 --- a/crates/ruma-api/tests/ui/07-error-type-attribute.rs +++ b/crates/ruma-api/tests/ui/07-error-type-attribute.rs @@ -15,7 +15,7 @@ ruma_api! { response: {} #[derive(Default)] - error: ruma_api::error::Void + error: ruma_api::error::MatrixError } fn main() {}