mirror of
https://github.com/tokio-rs/axum.git
synced 2024-10-23 17:36:39 +02:00
Implement OptionalFromRequestParts for Path<T>
… and deprecate OptionalPath.
This commit is contained in:
parent
265e65a783
commit
a654c89200
3 changed files with 40 additions and 12 deletions
|
@ -19,7 +19,9 @@ mod query;
|
|||
#[cfg(feature = "multipart")]
|
||||
pub mod multipart;
|
||||
|
||||
pub use self::{cached::Cached, optional_path::OptionalPath, with_rejection::WithRejection};
|
||||
#[allow(deprecated)]
|
||||
pub use self::optional_path::OptionalPath;
|
||||
pub use self::{cached::Cached, with_rejection::WithRejection};
|
||||
|
||||
#[cfg(feature = "cookie")]
|
||||
pub use self::cookie::CookieJar;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use axum::{
|
||||
async_trait,
|
||||
extract::{path::ErrorKind, rejection::PathRejection, FromRequestParts, Path},
|
||||
extract::{rejection::PathRejection, FromRequestParts, Path},
|
||||
RequestPartsExt,
|
||||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
|
@ -32,9 +32,11 @@ use serde::de::DeserializeOwned;
|
|||
/// .route("/blog/:page", get(render_blog));
|
||||
/// # let app: Router = app;
|
||||
/// ```
|
||||
#[deprecated = "Use Option<Path<_>> instead"]
|
||||
#[derive(Debug)]
|
||||
pub struct OptionalPath<T>(pub Option<T>);
|
||||
|
||||
#[allow(deprecated)]
|
||||
#[async_trait]
|
||||
impl<T, S> FromRequestParts<S> for OptionalPath<T>
|
||||
where
|
||||
|
@ -47,19 +49,15 @@ where
|
|||
parts: &mut http::request::Parts,
|
||||
_: &S,
|
||||
) -> Result<Self, Self::Rejection> {
|
||||
match parts.extract::<Path<T>>().await {
|
||||
Ok(Path(params)) => Ok(Self(Some(params))),
|
||||
Err(PathRejection::FailedToDeserializePathParams(e))
|
||||
if matches!(e.kind(), ErrorKind::WrongNumberOfParameters { got: 0, .. }) =>
|
||||
{
|
||||
Ok(Self(None))
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
parts
|
||||
.extract::<Option<Path<T>>>()
|
||||
.await
|
||||
.map(|opt| Self(opt.map(|Path(x)| x)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(deprecated)]
|
||||
mod tests {
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
|
|
|
@ -9,7 +9,11 @@ use crate::{
|
|||
util::PercentDecodedStr,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use axum_core::response::{IntoResponse, Response};
|
||||
use axum_core::{
|
||||
extract::OptionalFromRequestParts,
|
||||
response::{IntoResponse, Response},
|
||||
RequestPartsExt as _,
|
||||
};
|
||||
use http::{request::Parts, StatusCode};
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::{fmt, sync::Arc};
|
||||
|
@ -178,6 +182,30 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T, S> OptionalFromRequestParts<S> for Path<T>
|
||||
where
|
||||
T: DeserializeOwned + Send + 'static,
|
||||
S: Send + Sync,
|
||||
{
|
||||
type Rejection = PathRejection;
|
||||
|
||||
async fn from_request_parts(
|
||||
parts: &mut Parts,
|
||||
_state: &S,
|
||||
) -> Result<Option<Self>, Self::Rejection> {
|
||||
match parts.extract::<Self>().await {
|
||||
Ok(Self(params)) => Ok(Some(Self(params))),
|
||||
Err(PathRejection::FailedToDeserializePathParams(e))
|
||||
if matches!(e.kind(), ErrorKind::WrongNumberOfParameters { got: 0, .. }) =>
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this wrapper type is used as the deserializer error to hide the `serde::de::Error` impl which
|
||||
// would otherwise be public if we used `ErrorKind` as the error directly
|
||||
#[derive(Debug)]
|
||||
|
|
Loading…
Reference in a new issue