api: Introduce OutgoingResponse trait
This commit is contained in:
parent
6f5c1ee953
commit
b122dcc135
@ -116,7 +116,7 @@ impl Response {
|
|||||||
if segments.last().unwrap().ident == "Option" =>
|
if segments.last().unwrap().ident == "Option" =>
|
||||||
{
|
{
|
||||||
quote! {
|
quote! {
|
||||||
if let Some(header) = response.#field_name {
|
if let Some(header) = self.#field_name {
|
||||||
headers
|
headers
|
||||||
.insert(
|
.insert(
|
||||||
#http::header::#header_name,
|
#http::header::#header_name,
|
||||||
@ -129,7 +129,7 @@ impl Response {
|
|||||||
headers
|
headers
|
||||||
.insert(
|
.insert(
|
||||||
#http::header::#header_name,
|
#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() {
|
if let Some(field) = self.newtype_raw_body_field() {
|
||||||
let field_name = field.ident.as_ref().expect("expected field to have an identifier");
|
let field_name = field.ident.as_ref().expect("expected field to have an identifier");
|
||||||
let span = field.span();
|
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 body = if let Some(field) = self.newtype_body_field() {
|
||||||
let field_name = field.ident.as_ref().expect("expected field to have an identifier");
|
let field_name = field.ident.as_ref().expect("expected field to have an identifier");
|
||||||
let span = field.span();
|
let span = field.span();
|
||||||
quote_spanned!(span=> response.#field_name)
|
quote_spanned!(span=> self.#field_name)
|
||||||
} else {
|
} else {
|
||||||
let fields = self.fields.iter().filter_map(|response_field| {
|
let fields = self.fields.iter().filter_map(|response_field| {
|
||||||
if let ResponseField::Body(ref field) = *response_field {
|
if let ResponseField::Body(ref field) = *response_field {
|
||||||
@ -170,7 +170,7 @@ impl Response {
|
|||||||
|
|
||||||
Some(quote_spanned! {span=>
|
Some(quote_spanned! {span=>
|
||||||
#( #cfg_attrs )*
|
#( #cfg_attrs )*
|
||||||
#field_name: response.#field_name
|
#field_name: self.#field_name
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -285,10 +285,13 @@ impl Response {
|
|||||||
|
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
#[cfg(feature = "server")]
|
#[cfg(feature = "server")]
|
||||||
impl ::std::convert::TryFrom<Response> for #http::Response<Vec<u8>> {
|
impl #ruma_api::OutgoingResponse for Response {
|
||||||
type Error = #ruma_api::error::IntoHttpError;
|
fn try_into_http_response(
|
||||||
|
self,
|
||||||
fn try_from(response: Response) -> ::std::result::Result<Self, Self::Error> {
|
) -> ::std::result::Result<
|
||||||
|
#http::Response<::std::vec::Vec<u8>>,
|
||||||
|
#ruma_api::error::IntoHttpError,
|
||||||
|
> {
|
||||||
let mut resp_builder = #http::Response::builder()
|
let mut resp_builder = #http::Response::builder()
|
||||||
.header(#http::header::CONTENT_TYPE, "application/json");
|
.header(#http::header::CONTENT_TYPE, "application/json");
|
||||||
|
|
||||||
@ -300,8 +303,7 @@ impl Response {
|
|||||||
// This cannot fail because we parse each header value
|
// This cannot fail because we parse each header value
|
||||||
// checking for errors as each value is inserted and
|
// checking for errors as each value is inserted and
|
||||||
// we only allow keys from the `http::header` module.
|
// we only allow keys from the `http::header` module.
|
||||||
let response = resp_builder.body(#body).unwrap();
|
Ok(resp_builder.body(#body).unwrap())
|
||||||
Ok(response)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#[cfg(not(all(feature = "client", feature = "server")))]
|
#[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");
|
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 bytes::Buf;
|
||||||
use http::Method;
|
use http::Method;
|
||||||
@ -306,7 +306,7 @@ pub trait IncomingRequest: Sized {
|
|||||||
type EndpointError: EndpointError;
|
type EndpointError: EndpointError;
|
||||||
|
|
||||||
/// Response type to return when the request is successful.
|
/// Response type to return when the request is successful.
|
||||||
type OutgoingResponse: TryInto<http::Response<Vec<u8>>, Error = IntoHttpError>;
|
type OutgoingResponse: OutgoingResponse;
|
||||||
|
|
||||||
/// Metadata about the endpoint.
|
/// Metadata about the endpoint.
|
||||||
const METADATA: Metadata;
|
const METADATA: Metadata;
|
||||||
@ -315,6 +315,15 @@ pub trait IncomingRequest: Sized {
|
|||||||
fn try_from_http_request(req: http::Request<Vec<u8>>) -> Result<Self, FromHttpRequestError>;
|
fn try_from_http_request(req: http::Request<Vec<u8>>) -> Result<Self, FromHttpRequestError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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<http::Response<Vec<u8>>, IntoHttpError>;
|
||||||
|
}
|
||||||
|
|
||||||
/// Marker trait for requests that don't require authentication, for the client side.
|
/// Marker trait for requests that don't require authentication, for the client side.
|
||||||
pub trait OutgoingNonAuthRequest: OutgoingRequest {}
|
pub trait OutgoingNonAuthRequest: OutgoingRequest {}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use std::convert::TryFrom;
|
|
||||||
|
|
||||||
use http::header::{Entry, CONTENT_TYPE};
|
use http::header::{Entry, CONTENT_TYPE};
|
||||||
use ruma_api::{ruma_api, OutgoingRequest as _};
|
use ruma_api::{ruma_api, OutgoingRequest as _, OutgoingResponse as _};
|
||||||
|
|
||||||
ruma_api! {
|
ruma_api! {
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -30,7 +28,7 @@ ruma_api! {
|
|||||||
#[test]
|
#[test]
|
||||||
fn response_content_type_override() {
|
fn response_content_type_override() {
|
||||||
let res = Response { stuff: "magic".into() };
|
let res = Response { stuff: "magic".into() };
|
||||||
let mut http_res = http::Response::<Vec<u8>>::try_from(res).unwrap();
|
let mut http_res = res.try_into_http_response().unwrap();
|
||||||
|
|
||||||
// Test that we correctly replaced the default content type,
|
// Test that we correctly replaced the default content type,
|
||||||
// not adding another content-type header.
|
// not adding another content-type header.
|
||||||
|
@ -7,6 +7,7 @@ use http::{header::CONTENT_TYPE, method::Method};
|
|||||||
use ruma_api::{
|
use ruma_api::{
|
||||||
error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, ServerError, Void},
|
error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, ServerError, Void},
|
||||||
AuthScheme, EndpointError, IncomingRequest, IncomingResponse, Metadata, OutgoingRequest,
|
AuthScheme, EndpointError, IncomingRequest, IncomingResponse, Metadata, OutgoingRequest,
|
||||||
|
OutgoingResponse,
|
||||||
};
|
};
|
||||||
use ruma_identifiers::{RoomAliasId, RoomId};
|
use ruma_identifiers::{RoomAliasId, RoomId};
|
||||||
use ruma_serde::Outgoing;
|
use ruma_serde::Outgoing;
|
||||||
@ -113,10 +114,8 @@ impl IncomingResponse for Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Response> for http::Response<Vec<u8>> {
|
impl OutgoingResponse for Response {
|
||||||
type Error = IntoHttpError;
|
fn try_into_http_response(self) -> Result<http::Response<Vec<u8>>, IntoHttpError> {
|
||||||
|
|
||||||
fn try_from(_: Response) -> Result<http::Response<Vec<u8>>, Self::Error> {
|
|
||||||
let response = http::Response::builder()
|
let response = http::Response::builder()
|
||||||
.header(CONTENT_TYPE, "application/json")
|
.header(CONTENT_TYPE, "application/json")
|
||||||
.body(b"{}".to_vec())
|
.body(b"{}".to_vec())
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
use std::convert::TryFrom;
|
use ruma_api::{ruma_api, OutgoingRequest as _, OutgoingResponse as _};
|
||||||
|
|
||||||
use ruma_api::{ruma_api, OutgoingRequest as _};
|
|
||||||
|
|
||||||
ruma_api! {
|
ruma_api! {
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -27,7 +25,7 @@ fn empty_request_http_repr() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn empty_response_http_repr() {
|
fn empty_response_http_repr() {
|
||||||
let res = Response {};
|
let res = Response {};
|
||||||
let http_res = http::Response::<Vec<u8>>::try_from(res).unwrap();
|
let http_res = res.try_into_http_response().unwrap();
|
||||||
|
|
||||||
assert_eq!(http_res.body(), b"{}");
|
assert_eq!(http_res.body(), b"{}");
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use std::convert::TryFrom;
|
|
||||||
|
|
||||||
use bytes::Buf;
|
use bytes::Buf;
|
||||||
use ruma_api::{
|
use ruma_api::{
|
||||||
error::{FromHttpResponseError, IntoHttpError, Void},
|
error::{FromHttpResponseError, IntoHttpError, Void},
|
||||||
ruma_api, IncomingResponse,
|
ruma_api, IncomingResponse, OutgoingResponse,
|
||||||
};
|
};
|
||||||
use ruma_serde::Outgoing;
|
use ruma_serde::Outgoing;
|
||||||
|
|
||||||
@ -37,10 +35,8 @@ impl IncomingResponse for Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Response> for http::Response<Vec<u8>> {
|
impl OutgoingResponse for Response {
|
||||||
type Error = IntoHttpError;
|
fn try_into_http_response(self) -> Result<http::Response<Vec<u8>>, IntoHttpError> {
|
||||||
|
|
||||||
fn try_from(_: Response) -> Result<Self, Self::Error> {
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user