rama_http/service/web/endpoint/extract/
mod.rs

1//! Extract utilities to develop endpoint services efortless.
2
3use crate::{dep::http::request::Parts, dep::mime, header, HeaderMap, IntoResponse};
4use rama_core::Context;
5use std::future::Future;
6
7mod host;
8#[doc(inline)]
9pub use host::Host;
10
11mod authority;
12#[doc(inline)]
13pub use authority::Authority;
14
15mod path;
16#[doc(inline)]
17pub use path::Path;
18
19mod query;
20#[doc(inline)]
21pub use query::Query;
22
23mod method;
24mod request;
25
26mod typed_header;
27#[doc(inline)]
28pub use typed_header::{TypedHeader, TypedHeaderRejection, TypedHeaderRejectionReason};
29
30mod body;
31#[doc(inline)]
32pub use body::{Body, Bytes, Form, Json, Text};
33
34mod option;
35#[doc(inline)]
36pub use option::{OptionalFromRequest, OptionalFromRequestContextRefPair};
37
38/// Types that can be created from request parts.
39///
40/// Extractors that implement `FromRequestParts` cannot consume the request body and can thus be
41/// run in any order for handlers.
42///
43/// If your extractor needs to consume the request body then you should implement [`FromRequest`]
44/// and not [`FromRequestParts`].
45pub trait FromRequestContextRefPair<S>: Sized + Send + Sync + 'static {
46    /// If the extractor fails it'll use this "rejection" type. A rejection is
47    /// a kind of error that can be converted into a response.
48    type Rejection: IntoResponse;
49
50    /// Perform the extraction.
51    fn from_request_context_ref_pair(
52        ctx: &Context<S>,
53        parts: &Parts,
54    ) -> impl Future<Output = Result<Self, Self::Rejection>> + Send;
55}
56
57/// Types that can be created from requests.
58///
59/// Extractors that implement `FromRequest` can consume the request body and can thus only be run
60/// once for handlers.
61///
62/// If your extractor doesn't need to consume the request body then you should implement
63/// [`FromRequestParts`] and not [`FromRequest`].
64pub trait FromRequest: Sized + Send + Sync + 'static {
65    /// If the extractor fails it'll use this "rejection" type. A rejection is
66    /// a kind of error that can be converted into a response.
67    type Rejection: IntoResponse;
68
69    /// Perform the extraction.
70    fn from_request(
71        req: crate::Request,
72    ) -> impl Future<Output = Result<Self, Self::Rejection>> + Send;
73}
74
75fn has_any_content_type(headers: &HeaderMap, expected_content_types: &[&mime::Mime]) -> bool {
76    let content_type = if let Some(content_type) = headers.get(header::CONTENT_TYPE) {
77        content_type
78    } else {
79        return false;
80    };
81
82    let content_type = if let Ok(content_type) = content_type.to_str() {
83        content_type
84    } else {
85        return false;
86    };
87
88    expected_content_types
89        .iter()
90        .any(|ct| content_type.starts_with(ct.as_ref()))
91}