refactor: update router error handling

- Add not found error
- Update error output, use plain text instead of json
This commit is contained in:
xfy
2025-04-10 10:57:31 +08:00
parent 14cdf3b35d
commit 251f47f760
2 changed files with 31 additions and 18 deletions

View File

@ -1,27 +1,31 @@
use std::fmt::Display;
use axum::{
Json,
http::StatusCode,
response::{IntoResponse, Response},
};
use serde_json::json;
use serde_repr::*;
use tracing::error;
#[derive(thiserror::Error, Debug)]
pub enum RouteError {
// Common errors
#[error("{0}")]
Any(#[from] anyhow::Error),
#[error("{0}")]
Infallible(#[from] std::convert::Infallible),
// Route errors
#[error("route not found")]
RouteNotFound(),
}
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)]
#[repr(u16)]
pub enum ErrorCode {
Normal = 200,
InternalError = 1000,
InternalError = 500,
NotFound = 404,
}
impl Display for ErrorCode {
@ -30,7 +34,8 @@ impl Display for ErrorCode {
let res = match self {
Normal => "",
InternalError => "服务器内部错误",
InternalError => "Internal Server Error",
NotFound => "Resource Not Found",
};
f.write_str(res)?;
Ok(())
@ -38,15 +43,11 @@ impl Display for ErrorCode {
}
/// Log and return INTERNAL_SERVER_ERROR
fn log_internal_error<T: Display>(err: T) -> (StatusCode, ErrorCode, String) {
fn log_internal_error<T: Display>(err: T) -> (StatusCode, String) {
use ErrorCode::*;
error!("{err}");
(
StatusCode::INTERNAL_SERVER_ERROR,
InternalError,
"internal server error".to_string(),
)
(StatusCode::INTERNAL_SERVER_ERROR, InternalError.to_string())
}
// Tell axum how to convert `AppError` into a response.
@ -54,15 +55,17 @@ impl IntoResponse for RouteError {
fn into_response(self) -> Response {
use RouteError::*;
let (status_code, code, err_message) = match self {
let (status_code, err_message) = match self {
Any(err) => log_internal_error(err),
// route errors
RouteNotFound() => (StatusCode::NOT_FOUND, ErrorCode::NotFound.to_string()),
};
let body = Json(json!({
"code": code,
"message": code.to_string(),
"error": err_message
}));
(status_code, body).into_response()
// let body = Json(json!({
// "code": code,
// "message": code.to_string(),
// "error": err_message
// }));
(status_code, err_message).into_response()
}
}

View File

@ -1,3 +1,5 @@
use std::path::PathBuf;
use axum::{extract::Path, response::IntoResponse};
use http::Uri;
use tracing::debug;
@ -25,10 +27,18 @@ pub async fn serve(uri: Uri, Path(path): Path<String>) -> RouteResult<impl IntoR
// which is `host_route.location`
debug!("request: {:?} uri {}", path, parent_path);
let route_map = ROUTE_MAP.read().await;
// [TODO] custom error and not found page
let Some(host_route) = route_map.get(parent_path) else {
return Err(RouteError::Any(anyhow::anyhow!("route not found")));
return Err(RouteError::RouteNotFound());
};
debug!("route: {:?}", host_route);
let path = PathBuf::from(path);
let Some(index_name) = path.file_name() else {
return Err(RouteError::RouteNotFound());
};
// after route found
debug!("request index file {:?}", index_name);
// try find index file first
// let host_route = app
// .host_route
// .get(&request.uri().path().to_string())