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

View File

@ -65,7 +65,7 @@ pub enum IntoHttpError {
pub enum FromHttpRequestError {
/// Deserialization failed
#[error("deserialization failed: {0}")]
Deserialization(#[from] RequestDeserializationError),
Deserialization(RequestDeserializationError),
/// HTTP method mismatch
#[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.
#[derive(Debug, Error)]
#[error("{inner}")]
pub struct RequestDeserializationError {
inner: DeserializationError,
http_request: http::Request<Vec<u8>>,
}
impl RequestDeserializationError {
/// Creates a new `RequestDeserializationError` from the given deserialization error and http
/// request.
pub fn new(
inner: impl Into<DeserializationError>,
http_request: http::Request<Vec<u8>>,
) -> Self {
Self { inner: inner.into(), http_request }
impl<T> From<T> for RequestDeserializationError
where
T: Into<DeserializationError>,
{
fn from(err: T) -> Self {
Self { inner: err.into() }
}
}

View File

@ -363,17 +363,3 @@ pub struct Metadata {
/// What authentication scheme the server uses for this endpoint.
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 ruma_api::{
error::{FromHttpRequestError, FromHttpResponseError, IntoHttpError, ServerError, Void},
try_deserialize, AuthScheme, EndpointError, IncomingRequest, IncomingResponse, Metadata,
OutgoingRequest,
AuthScheme, EndpointError, IncomingRequest, IncomingResponse, Metadata, OutgoingRequest,
};
use ruma_identifiers::{RoomAliasId, RoomId};
use ruma_serde::Outgoing;
@ -70,19 +69,16 @@ impl IncomingRequest for Request {
fn try_from_http_request(
request: http::Request<Vec<u8>>,
) -> Result<Self, FromHttpRequestError> {
let request_body: RequestBody =
try_deserialize!(request, serde_json::from_slice(request.body().as_slice()));
let request_body: RequestBody = serde_json::from_slice(request.body().as_slice())?;
let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect();
Ok(Request {
room_id: request_body.room_id,
room_alias: {
let decoded = try_deserialize!(
request,
percent_encoding::percent_decode(path_segments[5].as_bytes()).decode_utf8(),
);
let decoded =
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> {
use std::convert::TryFrom;
use ruma_api::try_deserialize;
use ruma_events::EventContent;
use ruma_events::EventContent as _;
use serde_json::value::RawValue as RawJsonValue;
let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect();
let room_id = {
let decoded = try_deserialize!(
request,
percent_encoding::percent_decode(path_segments[4].as_bytes()).decode_utf8(),
);
let decoded =
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!(
request,
percent_encoding::percent_decode(path_segments[7].as_bytes()).decode_utf8(),
)
.into_owned();
let txn_id = percent_encoding::percent_decode(path_segments[7].as_bytes())
.decode_utf8()?
.into_owned();
let content = {
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!(
request,
percent_encoding::percent_decode(path_segments[6].as_bytes()).decode_utf8()
);
let event_type =
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 })

View File

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

View File

@ -111,42 +111,35 @@ impl ruma_api::IncomingRequest for IncomingRequest {
fn try_from_http_request(
request: http::Request<Vec<u8>>,
) -> 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 serde_json::value::RawValue as RawJsonValue;
let path_segments: Vec<&str> = request.uri().path()[1..].split('/').collect();
let room_id = {
let decoded = try_deserialize!(
request,
percent_encoding::percent_decode(path_segments[4].as_bytes()).decode_utf8()
);
let decoded =
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) {
Some(segment) => try_deserialize!(
request,
percent_encoding::percent_decode(segment.as_bytes()).decode_utf8()
)
.into_owned(),
None => "".into(),
};
let state_key = path_segments
.get(7)
.map(|segment| percent_encoding::percent_decode(segment.as_bytes()).decode_utf8())
.transpose()?
.unwrap_or(Cow::Borrowed(""))
.into_owned();
let content = {
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!(
request,
percent_encoding::percent_decode(path_segments[6].as_bytes()).decode_utf8()
);
let event_type =
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 })