custom extractors rejection
Some checks failed
Rust / Test (push) Has been cancelled
Rust / Rustfmt (push) Has been cancelled
Rust / Clippy (push) Has been cancelled
Rust / Code coverage (push) Has been cancelled

This commit is contained in:
Alphonse Paix
2025-09-27 02:28:04 +02:00
parent f9ae3f42a6
commit f43e143bf6
6 changed files with 68 additions and 13 deletions

View File

@@ -10,7 +10,8 @@ mod unsubscribe;
pub use admin::*;
use askama::Template;
use axum::{
http::HeaderMap,
extract::FromRequestParts,
http::{HeaderMap, request::Parts},
response::{Html, IntoResponse, Response},
};
pub use health_check::*;
@@ -19,6 +20,7 @@ pub use login::*;
pub use posts::*;
use rand::{Rng, distr::Alphanumeric};
use reqwest::StatusCode;
use serde::de::DeserializeOwned;
pub use subscriptions::*;
pub use subscriptions_confirm::*;
pub use unsubscribe::*;
@@ -61,6 +63,8 @@ pub enum AppError {
FormError(#[source] anyhow::Error),
#[error("Authentication is required.")]
NotAuthenticated,
#[error("Handler extractor failed.")]
Extractor(#[source] anyhow::Error),
}
impl From<anyhow::Error> for AppError {
@@ -124,6 +128,7 @@ impl IntoResponse for AppError {
headers.insert("HX-Redirect", "/login".parse().unwrap());
(StatusCode::OK, headers).into_response()
}
AppError::Extractor(_) => not_found_html(),
}
}
}
@@ -155,6 +160,50 @@ impl From<AuthError> for AppError {
}
pub async fn not_found() -> Response {
let template = HtmlTemplate(NotFoundTemplate);
(StatusCode::NOT_FOUND, template).into_response()
(StatusCode::NOT_FOUND, not_found_html()).into_response()
}
pub fn not_found_html() -> Response {
let template = HtmlTemplate(NotFoundTemplate);
template.into_response()
}
pub struct Path<T>(T);
impl<T, S> FromRequestParts<S> for Path<T>
where
T: DeserializeOwned + Send,
S: Send + Sync,
{
type Rejection = AppError;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
match axum::extract::Path::<T>::from_request_parts(parts, state).await {
Ok(value) => Ok(Self(value.0)),
Err(rejection) => Err(AppError::Extractor(anyhow::anyhow!(
"Path rejection: {:?}",
rejection
))),
}
}
}
pub struct Query<T>(pub T);
impl<T, S> FromRequestParts<S> for Query<T>
where
T: DeserializeOwned,
S: Send + Sync,
{
type Rejection = AppError;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
match axum::extract::Query::<T>::from_request_parts(parts, state).await {
Ok(value) => Ok(Self(value.0)),
Err(rejection) => Err(AppError::Extractor(anyhow::anyhow!(
"Query rejection: {:?}",
rejection
))),
}
}
}