Fix Uri extractor not being the full URI if using nest (#156)

This commit is contained in:
David Pedersen 2021-08-07 22:07:50 +02:00 committed by GitHub
parent a6b3e09827
commit c570fb2d52
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 2 deletions

View file

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Make `FromRequest` default to being generic over `axum::body::Body` ([#146](https://github.com/tokio-rs/axum/pull/146))
- Implement `std::error::Error` for all rejections ([#153](https://github.com/tokio-rs/axum/pull/153))
- Fix `Uri` extractor not being the full URI if using `nest` ([#156](https://github.com/tokio-rs/axum/pull/156))
## Breaking changes

View file

@ -244,7 +244,7 @@
//!
//! [`body::Body`]: crate::body::Body
use crate::response::IntoResponse;
use crate::{response::IntoResponse, routing::OriginalUri};
use async_trait::async_trait;
use http::{header, Extensions, HeaderMap, Method, Request, Uri, Version};
use rejection::*;
@ -377,7 +377,7 @@ impl<B> RequestParts<B> {
let (
http::request::Parts {
method,
uri,
mut uri,
version,
headers,
extensions,
@ -386,6 +386,10 @@ impl<B> RequestParts<B> {
body,
) = req.into_parts();
if let Some(original_uri) = extensions.get::<OriginalUri>() {
uri = original_uri.0.clone();
};
RequestParts {
method,
uri,

View file

@ -907,6 +907,11 @@ where
}
fn call(&mut self, mut req: Request<B>) -> Self::Future {
if req.extensions().get::<OriginalUri>().is_none() {
let original_uri = OriginalUri(req.uri().clone());
req.extensions_mut().insert(original_uri);
}
if let Some((prefix, captures)) = self.pattern.prefix_match(req.uri().path()) {
let without_prefix = strip_prefix(req.uri(), prefix);
*req.uri_mut() = without_prefix;
@ -921,6 +926,11 @@ where
}
}
/// `Nested` changes the incoming requests URI. This will be saved as an
/// extension so extractors can still access the original URI.
#[derive(Clone)]
pub(crate) struct OriginalUri(pub(crate) Uri);
fn strip_prefix(uri: &Uri, prefix: &str) -> Uri {
let path_and_query = if let Some(path_and_query) = uri.path_and_query() {
let new_path = if let Some(path) = path_and_query.path().strip_prefix(prefix) {

View file

@ -126,3 +126,35 @@ async fn nesting_at_root() {
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.text().await.unwrap(), "/foo/bar");
}
#[tokio::test]
async fn nested_url_extractor() {
let app = nest(
"/foo",
nest(
"/bar",
route("/baz", get(|uri: Uri| async move { uri.to_string() })).route(
"/qux",
get(|req: Request<Body>| async move { req.uri().to_string() }),
),
),
);
let addr = run_in_background(app).await;
let client = reqwest::Client::new();
let res = client
.get(format!("http://{}/foo/bar/baz", addr))
.send()
.await
.unwrap();
assert_eq!(res.text().await.unwrap(), "/foo/bar/baz");
let res = client
.get(format!("http://{}/foo/bar/qux", addr))
.send()
.await
.unwrap();
assert_eq!(res.text().await.unwrap(), "/foo/bar/qux");
}