Skip to content

Commit 83b03d0

Browse files
authored
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.
1 parent b807b52 commit 83b03d0

File tree

5 files changed

+40
-18
lines changed

5 files changed

+40
-18
lines changed

axum/Cargo.toml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ readme = "README.md"
1111
repository = "https://github.com/tokio-rs/axum"
1212

1313
[features]
14-
default = ["http1", "json", "tower-log"]
14+
default = ["http1", "json", "matched-path", "original-uri", "tower-log"]
1515
http1 = ["hyper/http1"]
1616
http2 = ["hyper/http2"]
1717
json = ["serde_json"]
18+
matched-path = []
1819
multipart = ["multer"]
20+
original-uri = []
1921
tower-log = ["tower/log"]
2022
ws = ["tokio-tungstenite", "sha-1", "base64"]
2123

@@ -84,10 +86,10 @@ rustdoc-args = ["--cfg", "docsrs"]
8486

8587
[package.metadata.playground]
8688
features = [
87-
"http1",
88-
"http2",
89-
"json",
90-
"multipart",
91-
"tower",
92-
"ws",
89+
"http1",
90+
"http2",
91+
"json",
92+
"multipart",
93+
"tower",
94+
"ws",
9395
]

axum/src/extract/mod.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ pub mod ws;
1515
mod content_length_limit;
1616
mod extension;
1717
mod form;
18-
mod matched_path;
1918
mod query;
2019
mod raw_query;
2120
mod request_parts;
@@ -31,17 +30,23 @@ pub use self::{
3130
extension::Extension,
3231
extractor_middleware::extractor_middleware,
3332
form::Form,
34-
matched_path::MatchedPath,
3533
path::Path,
3634
query::Query,
3735
raw_query::RawQuery,
38-
request_parts::OriginalUri,
3936
request_parts::{BodyStream, RawBody},
4037
};
4138
#[doc(no_inline)]
4239
#[cfg(feature = "json")]
4340
pub use crate::Json;
4441

42+
#[cfg(feature = "matched-path")]
43+
mod matched_path;
44+
45+
#[cfg(feature = "matched-path")]
46+
#[cfg_attr(docsrs, doc(cfg(feature = "matched-path")))]
47+
#[doc(inline)]
48+
pub use self::matched_path::MatchedPath;
49+
4550
#[cfg(feature = "multipart")]
4651
#[cfg_attr(docsrs, doc(cfg(feature = "multipart")))]
4752
pub mod multipart;
@@ -51,6 +56,11 @@ pub mod multipart;
5156
#[doc(inline)]
5257
pub use self::multipart::Multipart;
5358

59+
#[cfg(feature = "original-uri")]
60+
#[cfg_attr(docsrs, doc(cfg(feature = "original-uri")))]
61+
#[doc(inline)]
62+
pub use self::request_parts::OriginalUri;
63+
5464
#[cfg(feature = "ws")]
5565
#[cfg_attr(docsrs, doc(cfg(feature = "ws")))]
5666
#[doc(inline)]

axum/src/extract/request_parts.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ use sync_wrapper::SyncWrapper;
4343
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
4444
/// # };
4545
/// ```
46+
#[cfg(feature = "original-uri")]
4647
#[derive(Debug, Clone)]
4748
pub struct OriginalUri(pub Uri);
4849

50+
#[cfg(feature = "original-uri")]
4951
#[async_trait]
5052
impl<B> FromRequest<B> for OriginalUri
5153
where

axum/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,12 +305,16 @@
305305
//! `http1` | Enables hyper's `http1` feature | Yes
306306
//! `http2` | Enables hyper's `http2` feature | No
307307
//! `json` | Enables the [`Json`] type and some similar convenience functionality | Yes
308+
//! `matched-path` | Enables capturing of every request's router path and the [`MatchedPath`] extractor | Yes
308309
//! `multipart` | Enables parsing `multipart/form-data` requests with [`Multipart`] | No
310+
//! `original-uri` | Enables capturing of every request's original URI and the [`OriginalUri`] extractor | Yes
309311
//! `tower-log` | Enables `tower`'s `log` feature | Yes
310312
//! `ws` | Enables WebSockets support via [`extract::ws`] | No
311313
//!
312314
//! [`TypedHeader`]: crate::extract::TypedHeader
315+
//! [`MatchedPath`]: crate::extract::MatchedPath
313316
//! [`Multipart`]: crate::extract::Multipart
317+
//! [`OriginalUri`]: crate::extract::OriginalUri
314318
//! [`tower`]: https://crates.io/crates/tower
315319
//! [`tower-http`]: https://crates.io/crates/tower-http
316320
//! [`tokio`]: http://crates.io/crates/tokio
@@ -322,7 +326,6 @@
322326
//! [examples]: https://github.com/tokio-rs/axum/tree/main/examples
323327
//! [`Router::merge`]: crate::routing::Router::merge
324328
//! [`axum::Server`]: hyper::server::Server
325-
//! [`OriginalUri`]: crate::extract::OriginalUri
326329
//! [`Service`]: tower::Service
327330
//! [`Service::poll_ready`]: tower::Service::poll_ready
328331
//! [`Service`'s]: tower::Service

axum/src/routing/mod.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
use self::{future::RouterFuture, not_found::NotFound};
44
use crate::{
55
body::{boxed, Body, Bytes, HttpBody},
6-
extract::{
7-
connect_info::{Connected, IntoMakeServiceWithConnectInfo},
8-
MatchedPath, OriginalUri,
9-
},
6+
extract::connect_info::{Connected, IntoMakeServiceWithConnectInfo},
107
response::Response,
118
routing::strip_prefix::StripPrefix,
129
util::{try_downcast, ByteStr, PercentDecodedByteStr},
@@ -400,7 +397,10 @@ where
400397
let id = *match_.value;
401398
req.extensions_mut().insert(id);
402399

400+
#[cfg(feature = "matched-path")]
403401
if let Some(matched_path) = self.node.route_id_to_path.get(&id) {
402+
use crate::extract::MatchedPath;
403+
404404
let matched_path = if let Some(previous) = req.extensions_mut().get::<MatchedPath>() {
405405
// a previous `MatchedPath` might exist if we're inside a nested Router
406406
let previous = if let Some(previous) =
@@ -468,9 +468,14 @@ where
468468

469469
#[inline]
470470
fn call(&mut self, mut req: Request<B>) -> Self::Future {
471-
if req.extensions().get::<OriginalUri>().is_none() {
472-
let original_uri = OriginalUri(req.uri().clone());
473-
req.extensions_mut().insert(original_uri);
471+
#[cfg(feature = "original-uri")]
472+
{
473+
use crate::extract::OriginalUri;
474+
475+
if req.extensions().get::<OriginalUri>().is_none() {
476+
let original_uri = OriginalUri(req.uri().clone());
477+
req.extensions_mut().insert(original_uri);
478+
}
474479
}
475480

476481
let path = req.uri().path().to_owned();

0 commit comments

Comments
 (0)