micro_web/extract/
from_request.rs1use 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
46impl 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}