tosic_http/extractors/
mod.rs

1//! Extractors are used to automatically extract data from the request
2//! to be used in the handler
3//!
4//! Implementing the [`FromRequest`] trait on a type will create a new extractor
5
6use crate::error::response_error::ResponseError;
7use crate::request::{HttpPayload, HttpRequest};
8use crate::traits::from_request::FromRequest;
9use std::convert::Infallible;
10use std::future::Future;
11use thiserror::Error;
12
13pub mod data;
14pub mod json;
15pub mod path;
16pub mod query;
17
18pub use data::Data;
19pub use json::Json;
20pub use path::Path;
21pub use query::Query;
22
23#[derive(Debug, Error)]
24#[allow(missing_docs)]
25/// An error that can happen when extracting data
26pub enum ExtractionError {
27    #[error(transparent)]
28    Json(#[from] serde_json::Error),
29    #[error("Failed to parse query: {0}")]
30    Query(#[from] serde::de::value::Error),
31    #[error("Data with that type was not found")]
32    DataNotFound,
33    #[error(transparent)]
34    QuerySerialize(#[from] serde_urlencoded::ser::Error),
35    #[error("An error happened when getting the path parameter: {0}")]
36    Path(String),
37    #[error("Expected there to be param but there was none")]
38    MissingPathField,
39    #[error("Invalid length of data when extracting")]
40    InvalidLength,
41}
42
43impl<E> FromRequest for Option<E>
44where
45    E: FromRequest + Send,
46    E::Future: Send + 'static,
47{
48    type Error = Infallible;
49    type Future = impl Future<Output = Result<Option<E>, Self::Error>> + Send;
50
51    #[inline]
52    fn from_request(req: &HttpRequest, payload: &mut HttpPayload) -> Self::Future {
53        let future = E::from_request(req, payload);
54
55        async move {
56            match future.await {
57                Ok(value) => Ok(Some(value)),
58                Err(_) => Ok(None),
59            }
60        }
61    }
62}
63
64// FromRequest implementation for Result<E, Err>
65impl<E, Err> FromRequest for Result<E, Err>
66where
67    E: FromRequest + Send,
68    E::Future: Send + 'static,
69    Err: ResponseError + From<E::Error> + Send,
70{
71    type Error = Infallible;
72    type Future = impl Future<Output = Result<Result<E, Err>, Self::Error>> + Send;
73
74    #[inline]
75    fn from_request(req: &HttpRequest, payload: &mut HttpPayload) -> Self::Future {
76        let future = E::from_request(req, payload);
77
78        async move {
79            match future.await {
80                Ok(value) => Ok(Ok(value)),
81                Err(e) => Ok(Err(Err::from(e))),
82            }
83        }
84    }
85}