api: Stop storing the http::Request in RequestDeserializationError

This commit is contained in:
Jonas Platte 2021-04-10 15:06:50 +02:00
parent 2ac020173b
commit 6f5c1ee953
No known key found for this signature in database
GPG Key ID: CC154DE0E30B7C67
7 changed files with 67 additions and 118 deletions

View File

@ -304,7 +304,7 @@ impl Request {
body => body, body => body,
}; };
#ruma_api::try_deserialize!(request, #serde_json::from_slice(json)) #serde_json::from_slice(json)?
}; };
} }
} else { } else {
@ -330,14 +330,11 @@ impl Request {
_ => ( _ => (
quote! { str_value.to_owned() }, quote! { str_value.to_owned() },
quote! { quote! {
// FIXME: Not a missing json field, a missing header! return Err(
return Err(#ruma_api::error::RequestDeserializationError::new(
#ruma_api::error::HeaderDeserializationError::MissingHeader( #ruma_api::error::HeaderDeserializationError::MissingHeader(
#header_name_string.into() #header_name_string.into()
), ).into(),
request,
) )
.into())
}, },
), ),
}; };
@ -345,8 +342,7 @@ impl Request {
quote! { quote! {
#field_name: match headers.get(#http::header::#header_name) { #field_name: match headers.get(#http::header::#header_name) {
Some(header_value) => { Some(header_value) => {
let str_value = let str_value = header_value.to_str()?;
#ruma_api::try_deserialize!(request, header_value.to_str());
#some_case #some_case
} }
None => #none_case, None => #none_case,
@ -604,22 +600,16 @@ impl Request {
if self.query_map_field().is_some() { if self.query_map_field().is_some() {
quote! { quote! {
let request_query = #ruma_api::try_deserialize!( let request_query = #ruma_serde::urlencoded::from_str(
request, &request.uri().query().unwrap_or(""),
#ruma_serde::urlencoded::from_str( )?;
&request.uri().query().unwrap_or("")
),
);
} }
} else if self.has_query_fields() { } else if self.has_query_fields() {
quote! { quote! {
let request_query: <RequestQuery as #ruma_serde::Outgoing>::Incoming = let request_query: <RequestQuery as #ruma_serde::Outgoing>::Incoming =
#ruma_api::try_deserialize!(
request,
#ruma_serde::urlencoded::from_str( #ruma_serde::urlencoded::from_str(
&request.uri().query().unwrap_or("") &request.uri().query().unwrap_or("")
), )?;
);
} }
} else { } else {
TokenStream::new() TokenStream::new()
@ -741,16 +731,10 @@ impl Request {
quote! { quote! {
#path_var_ident: { #path_var_ident: {
let segment = path_segments[#i].as_bytes(); let segment = path_segments[#i].as_bytes();
let decoded = #ruma_api::try_deserialize!( let decoded =
request, #percent_encoding::percent_decode(segment).decode_utf8()?;
#percent_encoding::percent_decode(segment)
.decode_utf8(),
);
#ruma_api::try_deserialize!( ::std::convert::TryFrom::try_from(&*decoded)?
request,
::std::convert::TryFrom::try_from(&*decoded),
)
} }
} }
}, },

View File

@ -65,7 +65,7 @@ pub enum IntoHttpError {
pub enum FromHttpRequestError { pub enum FromHttpRequestError {
/// Deserialization failed /// Deserialization failed
#[error("deserialization failed: {0}")] #[error("deserialization failed: {0}")]
Deserialization(#[from] RequestDeserializationError), Deserialization(RequestDeserializationError),
/// HTTP method mismatch /// HTTP method mismatch
#[error("http method mismatch: expected {expected}, received: {received}")] #[error("http method mismatch: expected {expected}, received: {received}")]
@ -77,22 +77,28 @@ pub enum FromHttpRequestError {
}, },
} }
impl<T> From<T> for FromHttpRequestError
where
T: Into<RequestDeserializationError>,
{
fn from(err: T) -> Self {
Self::Deserialization(err.into())
}
}
/// An error that occurred when trying to deserialize a request. /// An error that occurred when trying to deserialize a request.
#[derive(Debug, Error)] #[derive(Debug, Error)]
#[error("{inner}")] #[error("{inner}")]
pub struct RequestDeserializationError { pub struct RequestDeserializationError {
inner: DeserializationError, inner: DeserializationError,
http_request: http::Request<Vec<u8>>,
} }
impl RequestDeserializationError { impl<T> From<T> for RequestDeserializationError
/// Creates a new `RequestDeserializationError` from the given deserialization error and http where
/// request. T: Into<DeserializationError>,
pub fn new( {
inner: impl Into<DeserializationError>, fn from(err: T) -> Self {
http_request: http::Request<Vec<u8>>, Self { inner: err.into() }
) -> Self {
Self { inner: inner.into(), http_request }
} }
} }

View File

@ -363,17 +363,3 @@ pub struct Metadata {
/// What authentication scheme the server uses for this endpoint. /// What authentication scheme the server uses for this endpoint.
pub authentication: AuthScheme, pub authentication: AuthScheme,
} }
#[doc(hidden)]
#[macro_export]
macro_rules! try_deserialize {
($kind:ident, $call:expr $(,)?) => {
$crate::try_deserialize!(@$kind, $kind, $call)
};
(@request, $kind:ident, $call:expr) => {
match $call {
Ok(val) => val,
Err(err) => return Err($crate::error::RequestDeserializationError::new(err, $kind).into()),
}
};
}

View File

@ -6,8 +6,7 @@ use bytes::Buf;
use http::{header::CONTENT_TYPE, method::Method}; 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},
try_deserialize, AuthScheme, EndpointError, IncomingRequest, IncomingResponse, Metadata, AuthScheme, EndpointError, IncomingRequest, IncomingResponse, Metadata, OutgoingRequest,
OutgoingRequest,
}; };
use ruma_identifiers::{RoomAliasId, RoomId}; use ruma_identifiers::{RoomAliasId, RoomId};
use ruma_serde::Outgoing; use ruma_serde::Outgoing;
@ -70,19 +69,16 @@ impl IncomingRequest for Request {
fn try_from_http_request( fn try_from_http_request(
request: http::Request<Vec<u8>>, request: http::Request<Vec<u8>>,
) -> Result<Self, FromHttpRequestError> { ) -> Result<Self, FromHttpRequestError> {
let request_body: RequestBody = let request_body: RequestBody = serde_json::from_slice(request.body().as_slice())?;
try_deserialize!(request, serde_json::from_slice(request.body().as_slice()));
let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect(); let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect();
Ok(Request { Ok(Request {
room_id: request_body.room_id, room_id: request_body.room_id,
room_alias: { room_alias: {
let decoded = try_deserialize!( let decoded =
request, percent_encoding::percent_decode(path_segments[5].as_bytes()).decode_utf8()?;
percent_encoding::percent_decode(path_segments[5].as_bytes()).decode_utf8(),
);
try_deserialize!(request, TryFrom::try_from(&*decoded)) TryFrom::try_from(&*decoded)?
}, },
}) })
} }

View File

@ -109,37 +109,30 @@ impl ruma_api::IncomingRequest for IncomingRequest {
) -> Result<Self, ruma_api::error::FromHttpRequestError> { ) -> Result<Self, ruma_api::error::FromHttpRequestError> {
use std::convert::TryFrom; use std::convert::TryFrom;
use ruma_api::try_deserialize; use ruma_events::EventContent as _;
use ruma_events::EventContent;
use serde_json::value::RawValue as RawJsonValue; use serde_json::value::RawValue as RawJsonValue;
let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect(); let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect();
let room_id = { let room_id = {
let decoded = try_deserialize!( let decoded =
request, percent_encoding::percent_decode(path_segments[4].as_bytes()).decode_utf8()?;
percent_encoding::percent_decode(path_segments[4].as_bytes()).decode_utf8(),
);
try_deserialize!(request, RoomId::try_from(&*decoded)) RoomId::try_from(&*decoded)?
}; };
let txn_id = try_deserialize!( let txn_id = percent_encoding::percent_decode(path_segments[7].as_bytes())
request, .decode_utf8()?
percent_encoding::percent_decode(path_segments[7].as_bytes()).decode_utf8(),
)
.into_owned(); .into_owned();
let content = { let content = {
let request_body: Box<RawJsonValue> = let request_body: Box<RawJsonValue> =
try_deserialize!(request, serde_json::from_slice(request.body().as_slice())); serde_json::from_slice(request.body().as_slice())?;
let event_type = try_deserialize!( let event_type =
request, percent_encoding::percent_decode(path_segments[6].as_bytes()).decode_utf8()?;
percent_encoding::percent_decode(path_segments[6].as_bytes()).decode_utf8()
);
try_deserialize!(request, AnyMessageEventContent::from_parts(&event_type, request_body)) AnyMessageEventContent::from_parts(&event_type, request_body)?
}; };
Ok(Self { room_id, txn_id, content }) Ok(Self { room_id, txn_id, content })

View File

@ -113,36 +113,27 @@ impl ruma_api::IncomingRequest for IncomingRequest {
) -> Result<Self, ruma_api::error::FromHttpRequestError> { ) -> Result<Self, ruma_api::error::FromHttpRequestError> {
use std::convert::TryFrom; use std::convert::TryFrom;
use ruma_api::try_deserialize;
let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect(); let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect();
let room_id = { let room_id = {
let decoded = try_deserialize!( let decoded =
request, percent_encoding::percent_decode(path_segments[4].as_bytes()).decode_utf8()?;
percent_encoding::percent_decode(path_segments[4].as_bytes()).decode_utf8()
);
try_deserialize!(request, RoomId::try_from(&*decoded)) RoomId::try_from(&*decoded)?
}; };
let event_type = { let event_type = {
let decoded = try_deserialize!( let decoded =
request, percent_encoding::percent_decode(path_segments[6].as_bytes()).decode_utf8()?;
percent_encoding::percent_decode(path_segments[6].as_bytes()).decode_utf8()
);
try_deserialize!(request, EventType::try_from(&*decoded)) EventType::try_from(&*decoded)?
}; };
let state_key = match path_segments.get(7) { let state_key = match path_segments.get(7) {
Some(segment) => { Some(segment) => {
let decoded = try_deserialize!( let decoded = percent_encoding::percent_decode(segment.as_bytes()).decode_utf8()?;
request,
percent_encoding::percent_decode(segment.as_bytes()).decode_utf8()
);
try_deserialize!(request, String::try_from(&*decoded)) String::try_from(&*decoded)?
} }
None => "".into(), None => "".into(),
}; };

View File

@ -111,42 +111,35 @@ impl ruma_api::IncomingRequest for IncomingRequest {
fn try_from_http_request( fn try_from_http_request(
request: http::Request<Vec<u8>>, request: http::Request<Vec<u8>>,
) -> Result<Self, ruma_api::error::FromHttpRequestError> { ) -> Result<Self, ruma_api::error::FromHttpRequestError> {
use std::convert::TryFrom; use std::{borrow::Cow, convert::TryFrom};
use ruma_api::try_deserialize;
use ruma_events::EventContent; use ruma_events::EventContent;
use serde_json::value::RawValue as RawJsonValue; use serde_json::value::RawValue as RawJsonValue;
let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect(); let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect();
let room_id = { let room_id = {
let decoded = try_deserialize!( let decoded =
request, percent_encoding::percent_decode(path_segments[4].as_bytes()).decode_utf8()?;
percent_encoding::percent_decode(path_segments[4].as_bytes()).decode_utf8()
);
try_deserialize!(request, RoomId::try_from(&*decoded)) RoomId::try_from(&*decoded)?
}; };
let state_key = match path_segments.get(7) { let state_key = path_segments
Some(segment) => try_deserialize!( .get(7)
request, .map(|segment| percent_encoding::percent_decode(segment.as_bytes()).decode_utf8())
percent_encoding::percent_decode(segment.as_bytes()).decode_utf8() .transpose()?
) .unwrap_or(Cow::Borrowed(""))
.into_owned(), .into_owned();
None => "".into(),
};
let content = { let content = {
let request_body: Box<RawJsonValue> = let request_body: Box<RawJsonValue> =
try_deserialize!(request, serde_json::from_slice(request.body().as_slice())); serde_json::from_slice(request.body().as_slice())?;
let event_type = try_deserialize!( let event_type =
request, percent_encoding::percent_decode(path_segments[6].as_bytes()).decode_utf8()?;
percent_encoding::percent_decode(path_segments[6].as_bytes()).decode_utf8()
);
try_deserialize!(request, AnyStateEventContent::from_parts(&event_type, request_body)) AnyStateEventContent::from_parts(&event_type, request_body)?
}; };
Ok(Self { room_id, state_key, content }) Ok(Self { room_id, state_key, content })