diff --git a/ruma-api-macros/src/api/response.rs b/ruma-api-macros/src/api/response.rs index 9d0fd065..11252b6d 100644 --- a/ruma-api-macros/src/api/response.rs +++ b/ruma-api-macros/src/api/response.rs @@ -116,7 +116,7 @@ impl Response { if segments.last().unwrap().ident == "Option" => { quote! { - if let Some(header) = response.#field_name { + if let Some(header) = self.#field_name { headers .insert( #http::header::#header_name, @@ -129,7 +129,7 @@ impl Response { headers .insert( #http::header::#header_name, - response.#field_name.parse()?, + self.#field_name.parse()?, ); }, }; @@ -152,13 +152,13 @@ impl Response { if let Some(field) = self.newtype_raw_body_field() { let field_name = field.ident.as_ref().expect("expected field to have an identifier"); let span = field.span(); - return quote_spanned!(span=> response.#field_name); + return quote_spanned!(span=> self.#field_name); } let body = if let Some(field) = self.newtype_body_field() { let field_name = field.ident.as_ref().expect("expected field to have an identifier"); let span = field.span(); - quote_spanned!(span=> response.#field_name) + quote_spanned!(span=> self.#field_name) } else { let fields = self.fields.iter().filter_map(|response_field| { if let ResponseField::Body(ref field) = *response_field { @@ -170,7 +170,7 @@ impl Response { Some(quote_spanned! {span=> #( #cfg_attrs )* - #field_name: response.#field_name + #field_name: self.#field_name }) } else { None @@ -285,10 +285,13 @@ impl Response { #[automatically_derived] #[cfg(feature = "server")] - impl ::std::convert::TryFrom for #http::Response> { - type Error = #ruma_api::error::IntoHttpError; - - fn try_from(response: Response) -> ::std::result::Result { + impl #ruma_api::OutgoingResponse for Response { + fn try_into_http_response( + self, + ) -> ::std::result::Result< + #http::Response<::std::vec::Vec>, + #ruma_api::error::IntoHttpError, + > { let mut resp_builder = #http::Response::builder() .header(#http::header::CONTENT_TYPE, "application/json"); @@ -300,8 +303,7 @@ impl Response { // This cannot fail because we parse each header value // checking for errors as each value is inserted and // we only allow keys from the `http::header` module. - let response = resp_builder.body(#body).unwrap(); - Ok(response) + Ok(resp_builder.body(#body).unwrap()) } } diff --git a/ruma-api/src/lib.rs b/ruma-api/src/lib.rs index a696c476..1f97268d 100644 --- a/ruma-api/src/lib.rs +++ b/ruma-api/src/lib.rs @@ -20,7 +20,7 @@ #[cfg(not(all(feature = "client", feature = "server")))] compile_error!("ruma_api's Cargo features only exist as a workaround are not meant to be disabled"); -use std::{convert::TryInto, error::Error as StdError}; +use std::{convert::TryInto as _, error::Error as StdError}; use bytes::Buf; use http::Method; @@ -306,7 +306,7 @@ pub trait IncomingRequest: Sized { type EndpointError: EndpointError; /// Response type to return when the request is successful. - type OutgoingResponse: TryInto>, Error = IntoHttpError>; + type OutgoingResponse: OutgoingResponse; /// Metadata about the endpoint. const METADATA: Metadata; @@ -315,6 +315,15 @@ pub trait IncomingRequest: Sized { fn try_from_http_request(req: http::Request>) -> Result; } +/// A request type for a Matrix API endpoint, used for sending responses. +pub trait OutgoingResponse { + /// Tries to convert this response into an `http::Response`. + /// + /// This method should only fail when when invalid header values are specified. It may also + /// fail with a serialization error in case of bugs in Ruma though. + fn try_into_http_response(self) -> Result>, IntoHttpError>; +} + /// Marker trait for requests that don't require authentication, for the client side. pub trait OutgoingNonAuthRequest: OutgoingRequest {} diff --git a/ruma-api/tests/header_override.rs b/ruma-api/tests/header_override.rs index b96b8a07..5f84a821 100644 --- a/ruma-api/tests/header_override.rs +++ b/ruma-api/tests/header_override.rs @@ -1,7 +1,5 @@ -use std::convert::TryFrom; - use http::header::{Entry, CONTENT_TYPE}; -use ruma_api::{ruma_api, OutgoingRequest as _}; +use ruma_api::{ruma_api, OutgoingRequest as _, OutgoingResponse as _}; ruma_api! { metadata: { @@ -30,7 +28,7 @@ ruma_api! { #[test] fn response_content_type_override() { let res = Response { stuff: "magic".into() }; - let mut http_res = http::Response::>::try_from(res).unwrap(); + let mut http_res = res.try_into_http_response().unwrap(); // Test that we correctly replaced the default content type, // not adding another content-type header. diff --git a/ruma-api/tests/manual_endpoint_impl.rs b/ruma-api/tests/manual_endpoint_impl.rs index fe39ddd0..6b5623eb 100644 --- a/ruma-api/tests/manual_endpoint_impl.rs +++ b/ruma-api/tests/manual_endpoint_impl.rs @@ -7,6 +7,7 @@ use http::{header::CONTENT_TYPE, method::Method}; use ruma_api::{ error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, ServerError, Void}, AuthScheme, EndpointError, IncomingRequest, IncomingResponse, Metadata, OutgoingRequest, + OutgoingResponse, }; use ruma_identifiers::{RoomAliasId, RoomId}; use ruma_serde::Outgoing; @@ -113,10 +114,8 @@ impl IncomingResponse for Response { } } -impl TryFrom for http::Response> { - type Error = IntoHttpError; - - fn try_from(_: Response) -> Result>, Self::Error> { +impl OutgoingResponse for Response { + fn try_into_http_response(self) -> Result>, IntoHttpError> { let response = http::Response::builder() .header(CONTENT_TYPE, "application/json") .body(b"{}".to_vec()) diff --git a/ruma-api/tests/no_fields.rs b/ruma-api/tests/no_fields.rs index f09a85bb..1e579fc8 100644 --- a/ruma-api/tests/no_fields.rs +++ b/ruma-api/tests/no_fields.rs @@ -1,6 +1,4 @@ -use std::convert::TryFrom; - -use ruma_api::{ruma_api, OutgoingRequest as _}; +use ruma_api::{ruma_api, OutgoingRequest as _, OutgoingResponse as _}; ruma_api! { metadata: { @@ -27,7 +25,7 @@ fn empty_request_http_repr() { #[test] fn empty_response_http_repr() { let res = Response {}; - let http_res = http::Response::>::try_from(res).unwrap(); + let http_res = res.try_into_http_response().unwrap(); assert_eq!(http_res.body(), b"{}"); } diff --git a/ruma-api/tests/ui/05-request-only.rs b/ruma-api/tests/ui/05-request-only.rs index 4035df54..49af1b29 100644 --- a/ruma-api/tests/ui/05-request-only.rs +++ b/ruma-api/tests/ui/05-request-only.rs @@ -1,9 +1,7 @@ -use std::convert::TryFrom; - use bytes::Buf; use ruma_api::{ error::{FromHttpResponseError, IntoHttpError, Void}, - ruma_api, IncomingResponse, + ruma_api, IncomingResponse, OutgoingResponse, }; use ruma_serde::Outgoing; @@ -37,10 +35,8 @@ impl IncomingResponse for Response { } } -impl TryFrom for http::Response> { - type Error = IntoHttpError; - - fn try_from(_: Response) -> Result { +impl OutgoingResponse for Response { + fn try_into_http_response(self) -> Result>, IntoHttpError> { todo!() } }