mirror of
https://github.com/tokio-rs/axum.git
synced 2026-08-29 00:00:18 +02:00
Optional extractor extensions (#685)
* Fix inconsistent indentation in axum/Cargo.toml * Make MatchedPath and OriginalUri extractors and logic for them optional … they add some runtime cost to handling any request that goes through a Router, which only makes sense if they actually get used. Enable both features by default for convenience.
This commit is contained in:
committed by
David Pedersen
parent
d97f2aeae6
commit
e0a463b463
+9
-7
@@ -11,11 +11,13 @@ readme = "README.md"
|
|||||||
repository = "https://github.com/tokio-rs/axum"
|
repository = "https://github.com/tokio-rs/axum"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["http1", "json", "tower-log"]
|
default = ["http1", "json", "matched-path", "original-uri", "tower-log"]
|
||||||
http1 = ["hyper/http1"]
|
http1 = ["hyper/http1"]
|
||||||
http2 = ["hyper/http2"]
|
http2 = ["hyper/http2"]
|
||||||
json = ["serde_json"]
|
json = ["serde_json"]
|
||||||
|
matched-path = []
|
||||||
multipart = ["multer"]
|
multipart = ["multer"]
|
||||||
|
original-uri = []
|
||||||
tower-log = ["tower/log"]
|
tower-log = ["tower/log"]
|
||||||
ws = ["tokio-tungstenite", "sha-1", "base64"]
|
ws = ["tokio-tungstenite", "sha-1", "base64"]
|
||||||
|
|
||||||
@@ -84,10 +86,10 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||||||
|
|
||||||
[package.metadata.playground]
|
[package.metadata.playground]
|
||||||
features = [
|
features = [
|
||||||
"http1",
|
"http1",
|
||||||
"http2",
|
"http2",
|
||||||
"json",
|
"json",
|
||||||
"multipart",
|
"multipart",
|
||||||
"tower",
|
"tower",
|
||||||
"ws",
|
"ws",
|
||||||
]
|
]
|
||||||
|
|||||||
+13
-3
@@ -15,7 +15,6 @@ pub mod ws;
|
|||||||
mod content_length_limit;
|
mod content_length_limit;
|
||||||
mod extension;
|
mod extension;
|
||||||
mod form;
|
mod form;
|
||||||
mod matched_path;
|
|
||||||
mod query;
|
mod query;
|
||||||
mod raw_query;
|
mod raw_query;
|
||||||
mod request_parts;
|
mod request_parts;
|
||||||
@@ -31,17 +30,23 @@ pub use self::{
|
|||||||
extension::Extension,
|
extension::Extension,
|
||||||
extractor_middleware::extractor_middleware,
|
extractor_middleware::extractor_middleware,
|
||||||
form::Form,
|
form::Form,
|
||||||
matched_path::MatchedPath,
|
|
||||||
path::Path,
|
path::Path,
|
||||||
query::Query,
|
query::Query,
|
||||||
raw_query::RawQuery,
|
raw_query::RawQuery,
|
||||||
request_parts::OriginalUri,
|
|
||||||
request_parts::{BodyStream, RawBody},
|
request_parts::{BodyStream, RawBody},
|
||||||
};
|
};
|
||||||
#[doc(no_inline)]
|
#[doc(no_inline)]
|
||||||
#[cfg(feature = "json")]
|
#[cfg(feature = "json")]
|
||||||
pub use crate::Json;
|
pub use crate::Json;
|
||||||
|
|
||||||
|
#[cfg(feature = "matched-path")]
|
||||||
|
mod matched_path;
|
||||||
|
|
||||||
|
#[cfg(feature = "matched-path")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "matched-path")))]
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use self::matched_path::MatchedPath;
|
||||||
|
|
||||||
#[cfg(feature = "multipart")]
|
#[cfg(feature = "multipart")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "multipart")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "multipart")))]
|
||||||
pub mod multipart;
|
pub mod multipart;
|
||||||
@@ -51,6 +56,11 @@ pub mod multipart;
|
|||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use self::multipart::Multipart;
|
pub use self::multipart::Multipart;
|
||||||
|
|
||||||
|
#[cfg(feature = "original-uri")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "original-uri")))]
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use self::request_parts::OriginalUri;
|
||||||
|
|
||||||
#[cfg(feature = "ws")]
|
#[cfg(feature = "ws")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "ws")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "ws")))]
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
|
|||||||
@@ -80,9 +80,11 @@ use sync_wrapper::SyncWrapper;
|
|||||||
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||||||
/// # };
|
/// # };
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "original-uri")]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct OriginalUri(pub Uri);
|
pub struct OriginalUri(pub Uri);
|
||||||
|
|
||||||
|
#[cfg(feature = "original-uri")]
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<B> FromRequest<B> for OriginalUri
|
impl<B> FromRequest<B> for OriginalUri
|
||||||
where
|
where
|
||||||
|
|||||||
+4
-1
@@ -375,12 +375,16 @@
|
|||||||
//! `http1` | Enables hyper's `http1` feature | Yes
|
//! `http1` | Enables hyper's `http1` feature | Yes
|
||||||
//! `http2` | Enables hyper's `http2` feature | No
|
//! `http2` | Enables hyper's `http2` feature | No
|
||||||
//! `json` | Enables the [`Json`] type and some similar convenience functionality | Yes
|
//! `json` | Enables the [`Json`] type and some similar convenience functionality | Yes
|
||||||
|
//! `matched-path` | Enables capturing of every request's router path and the [`MatchedPath`] extractor | Yes
|
||||||
//! `multipart` | Enables parsing `multipart/form-data` requests with [`Multipart`] | No
|
//! `multipart` | Enables parsing `multipart/form-data` requests with [`Multipart`] | No
|
||||||
|
//! `original-uri` | Enables capturing of every request's original URI and the [`OriginalUri`] extractor | Yes
|
||||||
//! `tower-log` | Enables `tower`'s `log` feature | Yes
|
//! `tower-log` | Enables `tower`'s `log` feature | Yes
|
||||||
//! `ws` | Enables WebSockets support via [`extract::ws`] | No
|
//! `ws` | Enables WebSockets support via [`extract::ws`] | No
|
||||||
//!
|
//!
|
||||||
//! [`TypedHeader`]: crate::extract::TypedHeader
|
//! [`TypedHeader`]: crate::extract::TypedHeader
|
||||||
|
//! [`MatchedPath`]: crate::extract::MatchedPath
|
||||||
//! [`Multipart`]: crate::extract::Multipart
|
//! [`Multipart`]: crate::extract::Multipart
|
||||||
|
//! [`OriginalUri`]: crate::extract::OriginalUri
|
||||||
//! [`tower`]: https://crates.io/crates/tower
|
//! [`tower`]: https://crates.io/crates/tower
|
||||||
//! [`tower-http`]: https://crates.io/crates/tower-http
|
//! [`tower-http`]: https://crates.io/crates/tower-http
|
||||||
//! [`tokio`]: http://crates.io/crates/tokio
|
//! [`tokio`]: http://crates.io/crates/tokio
|
||||||
@@ -392,7 +396,6 @@
|
|||||||
//! [examples]: https://github.com/tokio-rs/axum/tree/main/examples
|
//! [examples]: https://github.com/tokio-rs/axum/tree/main/examples
|
||||||
//! [`Router::merge`]: crate::routing::Router::merge
|
//! [`Router::merge`]: crate::routing::Router::merge
|
||||||
//! [`axum::Server`]: hyper::server::Server
|
//! [`axum::Server`]: hyper::server::Server
|
||||||
//! [`OriginalUri`]: crate::extract::OriginalUri
|
|
||||||
//! [`Service`]: tower::Service
|
//! [`Service`]: tower::Service
|
||||||
//! [`Service::poll_ready`]: tower::Service::poll_ready
|
//! [`Service::poll_ready`]: tower::Service::poll_ready
|
||||||
//! [`Service`'s]: tower::Service
|
//! [`Service`'s]: tower::Service
|
||||||
|
|||||||
+13
-10
@@ -3,13 +3,8 @@
|
|||||||
use self::{future::RouterFuture, not_found::NotFound};
|
use self::{future::RouterFuture, not_found::NotFound};
|
||||||
use crate::{
|
use crate::{
|
||||||
body::{boxed, Body, Bytes, HttpBody},
|
body::{boxed, Body, Bytes, HttpBody},
|
||||||
extract::{
|
extract::connect_info::{Connected, IntoMakeServiceWithConnectInfo},
|
||||||
connect_info::{Connected, IntoMakeServiceWithConnectInfo},
|
response::{Response, Redirect, IntoResponse},
|
||||||
MatchedPath, OriginalUri,
|
|
||||||
},
|
|
||||||
response::IntoResponse,
|
|
||||||
response::Redirect,
|
|
||||||
response::Response,
|
|
||||||
routing::strip_prefix::StripPrefix,
|
routing::strip_prefix::StripPrefix,
|
||||||
util::{try_downcast, ByteStr, PercentDecodedByteStr},
|
util::{try_downcast, ByteStr, PercentDecodedByteStr},
|
||||||
BoxError,
|
BoxError,
|
||||||
@@ -405,7 +400,10 @@ where
|
|||||||
let id = *match_.value;
|
let id = *match_.value;
|
||||||
req.extensions_mut().insert(id);
|
req.extensions_mut().insert(id);
|
||||||
|
|
||||||
|
#[cfg(feature = "matched-path")]
|
||||||
if let Some(matched_path) = self.node.route_id_to_path.get(&id) {
|
if let Some(matched_path) = self.node.route_id_to_path.get(&id) {
|
||||||
|
use crate::extract::MatchedPath;
|
||||||
|
|
||||||
let matched_path = if let Some(previous) = req.extensions_mut().get::<MatchedPath>() {
|
let matched_path = if let Some(previous) = req.extensions_mut().get::<MatchedPath>() {
|
||||||
// a previous `MatchedPath` might exist if we're inside a nested Router
|
// a previous `MatchedPath` might exist if we're inside a nested Router
|
||||||
let previous = if let Some(previous) =
|
let previous = if let Some(previous) =
|
||||||
@@ -476,9 +474,14 @@ where
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn call(&mut self, mut req: Request<B>) -> Self::Future {
|
fn call(&mut self, mut req: Request<B>) -> Self::Future {
|
||||||
if req.extensions().get::<OriginalUri>().is_none() {
|
#[cfg(feature = "original-uri")]
|
||||||
let original_uri = OriginalUri(req.uri().clone());
|
{
|
||||||
req.extensions_mut().insert(original_uri);
|
use crate::extract::OriginalUri;
|
||||||
|
|
||||||
|
if req.extensions().get::<OriginalUri>().is_none() {
|
||||||
|
let original_uri = OriginalUri(req.uri().clone());
|
||||||
|
req.extensions_mut().insert(original_uri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = req.uri().path().to_owned();
|
let path = req.uri().path().to_owned();
|
||||||
|
|||||||
Reference in New Issue
Block a user