diff --git a/axum-extra/Cargo.toml b/axum-extra/Cargo.toml index 50edeb42..768fed66 100644 --- a/axum-extra/Cargo.toml +++ b/axum-extra/Cargo.toml @@ -32,6 +32,7 @@ protobuf = ["dep:prost"] query = ["dep:serde", "dep:serde_html_form"] spa = ["tower-http/fs"] typed-routing = ["dep:axum-macros", "dep:serde", "dep:percent-encoding"] +with_rejection = [] [dependencies] axum = { path = "../axum", version = "0.5", default-features = false } diff --git a/axum-extra/src/extract/mod.rs b/axum-extra/src/extract/mod.rs index 22e19559..81d8ad11 100644 --- a/axum-extra/src/extract/mod.rs +++ b/axum-extra/src/extract/mod.rs @@ -11,6 +11,9 @@ pub mod cookie; #[cfg(feature = "query")] mod query; +#[cfg(feature = "with_rejection")] +mod with_rejection; + pub use self::cached::Cached; #[cfg(feature = "cookie")] @@ -31,3 +34,6 @@ pub use self::query::Query; #[cfg(feature = "json-lines")] #[doc(no_inline)] pub use crate::json_lines::JsonLines; + +#[cfg(feature = "with_rejection")] +pub use self::with_rejection::WithRejection; diff --git a/axum-extra/src/extract/with_rejection.rs b/axum-extra/src/extract/with_rejection.rs new file mode 100644 index 00000000..0b20641f --- /dev/null +++ b/axum-extra/src/extract/with_rejection.rs @@ -0,0 +1,45 @@ +use axum::async_trait; +use axum::extract::{FromRequest, RequestParts}; +use axum::response::IntoResponse; +use std::marker::PhantomData; +use std::ops::{Deref, DerefMut}; + +#[derive(Debug, Clone, Copy, Default)] +pub struct WithRejection(pub E, pub PhantomData); + +impl WithRejection { + fn into_inner(self) -> E { + self.0 + } +} + +impl Deref for WithRejection { + type Target = E; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for WithRejection { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +#[async_trait] +impl FromRequest for WithRejection +where + B: Send, + E: FromRequest, + R: From + IntoResponse, +{ + type Rejection = R; + + async fn from_request(req: &mut RequestParts) -> Result { + match req.extract::().await { + Ok(extractor) => Ok(WithRejection(extractor, PhantomData)), + Err(err) => Err(err.into()), + } + } +}