micro_web/extract/
from_request.rs

1use crate::responder::Responder;
2use crate::{OptionReqBody, RequestContext, ResponseBody};
3use http::{Response, StatusCode};
4use micro_http::protocol::ParseError;
5use std::convert::Infallible;
6
7#[trait_variant::make(Send)]
8pub trait FromRequest {
9    type Output<'r>: Send;
10    type Error: Responder + Send;
11
12    #[allow(unused)]
13    async fn from_request<'r>(req: &'r RequestContext<'_, '_>, body: OptionReqBody) -> Result<Self::Output<'r>, Self::Error>;
14}
15
16impl<T: FromRequest> FromRequest for Option<T> {
17    type Output<'r> = Option<T::Output<'r>>;
18    type Error = T::Error;
19
20    async fn from_request<'r>(req: &'r RequestContext<'_, '_>, body: OptionReqBody) -> Result<Self::Output<'r>, Self::Error> {
21        match T::from_request(req, body).await {
22            Ok(result) => Ok(Some(result)),
23            Err(_err) => Ok(None),
24        }
25    }
26}
27
28impl<T: FromRequest> FromRequest for Result<T, T::Error> {
29    type Output<'r> = Result<T::Output<'r>, T::Error>;
30    type Error = T::Error;
31
32    async fn from_request<'r>(req: &'r RequestContext<'_, '_>, body: OptionReqBody) -> Result<Self::Output<'r>, Self::Error> {
33        Ok(T::from_request(req, body).await)
34    }
35}
36
37impl FromRequest for () {
38    type Output<'r> = ();
39    type Error = Infallible;
40
41    async fn from_request<'r>(_req: &'r RequestContext<'_, '_>, _body: OptionReqBody) -> Result<Self::Output<'r>, Self::Error> {
42        Ok(())
43    }
44}
45
46/// Responder implementation for ParseError to convert parsing errors to responses
47impl Responder for ParseError {
48    fn response_to(self, req: &RequestContext) -> Response<ResponseBody> {
49        match self {
50            ParseError::TooLargeHeader { .. } => (StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE, "payload too large").response_to(req),
51            ParseError::TooManyHeaders { .. } => (StatusCode::BAD_REQUEST, "too many headers").response_to(req),
52            ParseError::InvalidHeader { .. } => (StatusCode::BAD_REQUEST, "invalid header").response_to(req),
53            ParseError::InvalidVersion(_) => (StatusCode::BAD_REQUEST, "invalid version").response_to(req),
54            ParseError::InvalidMethod => (StatusCode::BAD_REQUEST, "invalid method").response_to(req),
55            ParseError::InvalidUri => (StatusCode::BAD_REQUEST, "invalid uri").response_to(req),
56            ParseError::InvalidContentLength { .. } => (StatusCode::BAD_REQUEST, "invalid content length").response_to(req),
57            ParseError::InvalidBody { .. } => (StatusCode::BAD_REQUEST, "invalid body").response_to(req),
58            ParseError::Io { .. } => (StatusCode::BAD_REQUEST, "connection error").response_to(req),
59        }
60    }
61}