predawn_core/
from_request.rs1use std::{convert::Infallible, future::Future};
2
3use bytes::Bytes;
4use futures_util::FutureExt;
5use http::{HeaderMap, Method, Uri, Version};
6use http_body_util::{BodyExt, LengthLimitError};
7use snafu::{IntoError, ResultExt};
8
9use crate::{
10 body::RequestBody,
11 location::Location,
12 private::{ViaRequest, ViaRequestHead},
13 request::{BodyLimit, Head, LocalAddr, OriginalUri, RemoteAddr},
14 response_error::{
15 InvalidUtf8Snafu, ReadBytesError, ReadBytesSnafu, ReadStringError, RequestBodyLimitError,
16 RequestBodyLimitSnafu, ResponseError, UnknownBodySnafu,
17 },
18};
19
20pub trait FromRequestHead<'a>: Sized {
21 type Error: ResponseError;
22
23 fn from_request_head(
24 head: &'a mut Head,
25 ) -> impl Future<Output = Result<Self, Self::Error>> + Send;
26}
27
28pub trait FromRequest<'a, M = ViaRequest>: Sized {
29 type Error: ResponseError;
30
31 fn from_request(
32 head: &'a mut Head,
33 body: RequestBody,
34 ) -> impl Future<Output = Result<Self, Self::Error>> + Send;
35}
36
37impl<'a, T> FromRequest<'a, ViaRequestHead> for T
38where
39 T: FromRequestHead<'a>,
40{
41 type Error = T::Error;
42
43 async fn from_request(head: &'a mut Head, _: RequestBody) -> Result<Self, Self::Error> {
44 T::from_request_head(head).boxed().await
46 }
47}
48
49impl<'a, T: FromRequestHead<'a>> FromRequestHead<'a> for Option<T> {
50 type Error = Infallible;
51
52 async fn from_request_head(head: &'a mut Head) -> Result<Self, Self::Error> {
53 Ok(T::from_request_head(head).boxed().await.ok())
55 }
56}
57
58impl<'a, T: FromRequest<'a>> FromRequest<'a> for Option<T> {
59 type Error = Infallible;
60
61 async fn from_request(head: &'a mut Head, body: RequestBody) -> Result<Self, Self::Error> {
62 Ok(T::from_request(head, body).boxed().await.ok())
64 }
65}
66
67impl<'a, T: FromRequestHead<'a>> FromRequestHead<'a> for Result<T, T::Error> {
68 type Error = Infallible;
69
70 async fn from_request_head(head: &'a mut Head) -> Result<Self, Self::Error> {
71 Ok(T::from_request_head(head).boxed().await)
73 }
74}
75
76impl<'a, T: FromRequest<'a>> FromRequest<'a> for Result<T, T::Error> {
77 type Error = Infallible;
78
79 async fn from_request(head: &'a mut Head, body: RequestBody) -> Result<Self, Self::Error> {
80 Ok(T::from_request(head, body).boxed().await)
82 }
83}
84
85impl<'a> FromRequest<'a> for RequestBody {
86 type Error = Infallible;
87
88 async fn from_request(_: &'a mut Head, body: RequestBody) -> Result<Self, Self::Error> {
89 Ok(body)
90 }
91}
92
93impl<'a> FromRequest<'a> for Bytes {
94 type Error = ReadBytesError;
95
96 async fn from_request(head: &'a mut Head, body: RequestBody) -> Result<Self, Self::Error> {
97 match body.collect().await {
98 Ok(collected) => Ok(collected.to_bytes()),
99 Err(err) => match err.downcast::<LengthLimitError>() {
100 Ok(_) => Err(RequestBodyLimitSnafu.into_error(RequestBodyLimitError {
101 location: Location::caller(),
102 actual: head.content_length(),
103 expected: head.body_limit.0,
104 })),
105 Err(err) => Err(UnknownBodySnafu.into_error(err)),
106 },
107 }
108 }
109}
110
111impl<'a> FromRequest<'a> for Vec<u8> {
112 type Error = ReadBytesError;
113
114 async fn from_request(head: &'a mut Head, body: RequestBody) -> Result<Self, Self::Error> {
115 Ok(Bytes::from_request(head, body).await?.into())
116 }
117}
118
119impl<'a> FromRequest<'a> for String {
120 type Error = ReadStringError;
121
122 async fn from_request(head: &'a mut Head, body: RequestBody) -> Result<Self, Self::Error> {
123 let bytes = Vec::<u8>::from_request(head, body)
124 .await
125 .context(ReadBytesSnafu)?;
126
127 let string = String::from_utf8(bytes).context(InvalidUtf8Snafu)?;
128
129 Ok(string)
130 }
131}
132
133macro_rules! some_impl {
134 ($ty:ty; $($field:ident)?) => {
135 impl<'a> FromRequestHead<'a> for $ty {
136 type Error = Infallible;
137
138 async fn from_request_head(head: &'a mut Head) -> Result<Self, Self::Error> {
139 Ok(Clone::clone(&head $(.$field)?))
140 }
141 }
142 };
143}
144
145some_impl!(Head; );
146some_impl!(Uri; uri);
147some_impl!(Method; method);
148some_impl!(HeaderMap; headers);
149some_impl!(OriginalUri; original_uri);
150some_impl!(Version; version);
151some_impl!(LocalAddr; local_addr);
152some_impl!(RemoteAddr; remote_addr);
153some_impl!(BodyLimit; body_limit);