use super::{constants::*, defer::*};
use {
axum::{
extract::{Request, *},
http::*,
middleware::*,
response::{Response, *},
},
kutil::http::file::*,
std::{path::*, result::Result},
};
#[derive(Clone, Debug)]
pub struct CatchMiddleware {
pub assets_path: PathBuf,
}
impl CatchMiddleware {
pub fn new(assets_path: PathBuf) -> Self {
Self { assets_path }
}
pub async fn function(
State(state_self): State<Self>,
request: Request,
next: Next,
) -> Result<Response, StatusCode> {
if let Some(deferred_response) = DeferredResponse::get(&request) {
match deferred_response {
DeferredResponse::Hide => {
if let Some(response) = state_self.response(StatusCode::NOT_FOUND).await {
return Ok(response);
}
}
DeferredResponse::Authenticate(authenticate) => {
return Ok(DeferredResponse::authenticate(authenticate));
}
DeferredResponse::RedirectTo((uri_path, status_code)) => {
return Ok(DeferredResponse::redirect_to(uri_path, *status_code));
}
DeferredResponse::Error(message) => {
tracing::error!("{}", message);
if let Some(response) = state_self.response(StatusCode::INTERNAL_SERVER_ERROR).await {
return Ok(response);
}
}
_ => {}
}
}
let response = next.run(request).await;
let status = response.status();
if !status.is_success() {
if let Some(response) = state_self.response(status).await {
return Ok(response);
}
}
Ok(response)
}
pub async fn response(&self, status: StatusCode) -> Option<Response> {
let status = status.as_u16();
let file_path = self.assets_path.join(status.to_string() + HTML_SUFFIX);
if file_path.exists() {
tracing::debug!("status page: {}", status);
return Some(response_from_file(file_path, false).await.into_response());
}
None
}
}