Skip to content

Commit ac3856a

Browse files
authored
Merge pull request #5802 from Turbo87/axum-path-params
RequestParamExt: Use `axum` path parameters if available
2 parents 802f7ec + 63c9ebd commit ac3856a

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

conduit-axum/src/fallback.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ use crate::error::ServiceError;
33
use crate::file_stream::FileStream;
44
use crate::{spawn_blocking, AxumResponse, ConduitResponse};
55

6+
use std::collections::BTreeMap;
67
use std::error::Error;
78
use std::future::Future;
89
use std::pin::Pin;
910
use std::sync::Arc;
1011

1112
use axum::body::{Body, HttpBody};
12-
use axum::extract::Extension;
13+
use axum::extract::{rejection::PathRejection, Extension, FromRequestParts, Path};
1314
use axum::handler::Handler as AxumHandler;
1415
use axum::response::IntoResponse;
1516
use conduit::{Handler, RequestExt};
@@ -57,18 +58,29 @@ where
5758
{
5859
type Future = Pin<Box<dyn Future<Output = AxumResponse> + Send>>;
5960

60-
fn call(self, request: Request<Body>, _state: S) -> Self::Future {
61+
fn call(self, request: Request<Body>, state: S) -> Self::Future {
6162
Box::pin(async move {
6263
if let Err(response) = check_content_length(&request) {
6364
return response.into_response();
6465
}
6566

66-
let (parts, body) = request.into_parts();
67+
let (mut parts, body) = request.into_parts();
68+
69+
// Make `axum::Router` path params available to `conduit` compat
70+
// handlers. (see [RequestParamsExt] below)
71+
match Params::from_request_parts(&mut parts, &state).await {
72+
Ok(path) => {
73+
parts.extensions.insert(path);
74+
}
75+
Err(PathRejection::MissingPathParams(_)) => {}
76+
Err(err) => return err.into_response(),
77+
};
6778

6879
let full_body = match hyper::body::to_bytes(body).await {
6980
Ok(body) => body,
7081
Err(err) => return server_error_response(&err),
7182
};
83+
7284
let request = Request::from_parts(parts, full_body);
7385

7486
let Self(handler) = self;
@@ -174,3 +186,15 @@ fn check_content_length(request: &Request<Body>) -> Result<(), AxumResponse> {
174186

175187
Ok(())
176188
}
189+
190+
pub type Params = Path<BTreeMap<String, String>>;
191+
192+
pub trait RequestParamsExt<'a> {
193+
fn axum_params(self) -> Option<&'a Params>;
194+
}
195+
196+
impl<'a> RequestParamsExt<'a> for &'a (dyn RequestExt + 'a) {
197+
fn axum_params(self) -> Option<&'a Params> {
198+
self.extensions().get::<Params>()
199+
}
200+
}

conduit-axum/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ mod tokio_utils;
5656
pub use error::ServiceError;
5757
pub use fallback::{
5858
conduit_into_axum, CauseField, ConduitAxumHandler, ConduitFallback, ErrorField,
59+
RequestParamsExt,
5960
};
6061
pub use server::Server;
6162
pub use tokio_utils::spawn_blocking;

src/controllers/util.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::prelude::*;
22
use crate::util::errors::{forbidden, internal, AppError, AppResult};
3+
use conduit_axum::RequestParamsExt;
34
use conduit_router::RequestParams;
45

56
/// The Origin header (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin)
@@ -30,6 +31,10 @@ pub trait RequestParamExt<'a> {
3031

3132
impl<'a> RequestParamExt<'a> for &'a (dyn RequestExt + 'a) {
3233
fn param(self, key: &str) -> Option<&'a str> {
33-
self.params().find(key)
34+
return if let Some(params) = self.axum_params() {
35+
params.0.get(key).map(|s| &s[..])
36+
} else {
37+
self.params().find(key)
38+
};
3439
}
3540
}

0 commit comments

Comments
 (0)