axum/extract/
mod.rs

1#![doc = include_str!("../docs/extract.md")]
2
3use http::header::{self, HeaderMap};
4
5#[cfg(feature = "tokio")]
6pub mod connect_info;
7pub mod path;
8pub mod rejection;
9
10#[cfg(feature = "ws")]
11pub mod ws;
12
13mod host;
14pub(crate) mod nested_path;
15mod raw_form;
16mod raw_query;
17mod request_parts;
18mod state;
19
20#[doc(inline)]
21pub use axum_core::extract::{DefaultBodyLimit, FromRef, FromRequest, FromRequestParts, Request};
22
23#[cfg(feature = "macros")]
24pub use axum_macros::{FromRef, FromRequest, FromRequestParts};
25
26#[doc(inline)]
27#[allow(deprecated)]
28pub use self::{
29    host::Host,
30    nested_path::NestedPath,
31    path::{Path, RawPathParams},
32    raw_form::RawForm,
33    raw_query::RawQuery,
34    state::State,
35};
36
37#[doc(inline)]
38#[cfg(feature = "tokio")]
39pub use self::connect_info::ConnectInfo;
40
41#[doc(no_inline)]
42#[cfg(feature = "json")]
43pub use crate::Json;
44
45#[doc(no_inline)]
46pub use crate::Extension;
47
48#[cfg(feature = "form")]
49#[doc(no_inline)]
50pub use crate::form::Form;
51
52#[cfg(feature = "matched-path")]
53pub(crate) mod matched_path;
54
55#[cfg(feature = "matched-path")]
56#[doc(inline)]
57pub use self::matched_path::MatchedPath;
58
59#[cfg(feature = "multipart")]
60pub mod multipart;
61
62#[cfg(feature = "multipart")]
63#[doc(inline)]
64pub use self::multipart::Multipart;
65
66#[cfg(feature = "query")]
67mod query;
68
69#[cfg(feature = "query")]
70#[doc(inline)]
71pub use self::query::Query;
72
73#[cfg(feature = "original-uri")]
74#[doc(inline)]
75pub use self::request_parts::OriginalUri;
76
77#[cfg(feature = "ws")]
78#[doc(inline)]
79pub use self::ws::WebSocketUpgrade;
80
81// this is duplicated in `axum-extra/src/extract/form.rs`
82pub(super) fn has_content_type(headers: &HeaderMap, expected_content_type: &mime::Mime) -> bool {
83    let content_type = if let Some(content_type) = headers.get(header::CONTENT_TYPE) {
84        content_type
85    } else {
86        return false;
87    };
88
89    let content_type = if let Ok(content_type) = content_type.to_str() {
90        content_type
91    } else {
92        return false;
93    };
94
95    content_type.starts_with(expected_content_type.as_ref())
96}
97
98#[cfg(test)]
99mod tests {
100    use crate::{routing::get, test_helpers::*, Router};
101
102    #[crate::test]
103    async fn consume_body() {
104        let app = Router::new().route("/", get(|body: String| async { body }));
105
106        let client = TestClient::new(app);
107        let res = client.get("/").body("foo").await;
108        let body = res.text().await;
109
110        assert_eq!(body, "foo");
111    }
112}