2 个不稳定版本

0.1.0 2023 年 12 月 27 日
0.0.0 2023 年 12 月 27 日

#9#http-status

MIT 许可证

14KB
162 代码行

Axum-dyn-error

为 Axum HTTP 处理器实现动态错误处理

[dependencies]
axum-dyn-error = "0.1"

仅支持 axum v0.6

此crate提供创建和处理动态HTTP错误的基础逻辑。

通过在错误上实现HttpError trait,您可以自定义错误及其在错误响应中的显示方式。

我建议使用thiserror来定义您的用户界面错误类型。

为了使用动态错误处理,您应将您的[Result]返回类型替换为axum_dyn_error中的[HttpResult]类型。


use axum_dyn_error::{HttpResult, HttpError, StatusCode};
use thiserror::Error;
use axum::{extract::Path, Json};

#[derive(Debug, Error)]
pub enum ExampleError {
    #[error("User not found")]
    MissingUser,
    #[error("Username was invalid")]
    InvalidUsername
}

impl HttpError for ExampleError {

    /// Customize the HTTP status code
    fn status(&self) -> StatusCode {
        match self {
            ExampleError::MissingUser => StatusCode::NOT_FOUND,
            ExampleError::InvalidUsername => StatusCode::BAD_REQUEST
        }
    }
}

/// Dummy structure representing a user
pub struct User;

/// Mock function for finding a user by id
pub async fn get_user_by_id(user_id: u32) -> Option<User> { unimplemented!() }

/// Example handler
pub async fn example_handler(
    Path(user_id): Path<u32>
) -> HttpResult<Json<User>> {
    let user = get_user_by_id(user_id)
        .await
        .ok_or(ExampleError::MissingUser)?;

    Ok(Json(user))
}

Anyhow 支持

Axum-dyn-error 通过anyhow功能标志支持anyhow错误,默认情况下启用hide-anyhow功能标志,这会阻止将anyhow错误消息包含在错误响应中,而是响应“服务器错误”。


use axum_dyn_error::{HttpResult, HttpError, StatusCode};
use axum::{extract::Path, Json};
use anyhow::anyhow;

/// Dummy structure representing a user
pub struct User;

/// Mock function for finding a user by id
pub async fn get_user_by_id(user_id: u32) -> Option<User> { unimplemented!() }

/// Example handler
pub async fn example_handler(
    Path(user_id): Path<u32>
) -> HttpResult<Json<User>> {
    let user = get_user_by_id(user_id)
        .await
        .ok_or(anyhow!("Missing user"))?;

    Ok(Json(user))
}

使用[AnyhowStatusExt],anyhow错误类型可以关联HTTP状态码,默认情况下anyhow错误仅使用“500 内部服务器错误”。


use axum_dyn_error::{HttpResult, HttpError, StatusCode, anyhow::AnyhowStatusExt};
use axum::{extract::Path, Json};
use anyhow::anyhow;

/// Dummy structure representing a user
pub struct User;

/// Mock function for finding a user by id
pub async fn get_user_by_id(user_id: u32) -> Option<User> { unimplemented!() }

/// Example handler
pub async fn example_handler(
    Path(user_id): Path<u32>
) -> HttpResult<Json<User>> {
    let user = get_user_by_id(user_id)
        .await
        .ok_or(
            anyhow!("Missing user")
                .status(StatusCode::NOT_FOUND)
        )?;

    Ok(Json(user))
}

自定义响应

默认情况下,从错误生成的响应使用“原因”作为文本响应体。您可以通过创建一个结构并在此结构上实现IntoHttpErrorResponse来更改此设置。


use axum_dyn_error::{HttpResult, HttpError, IntoHttpErrorResponse};
use axum::response::{Response, IntoResponse};

pub struct CustomErrorResponse;

impl IntoHttpErrorResponse for CustomErrorResponse {
    fn into_response(error: Box<dyn HttpError>) -> Response {
        // Your logic to create the response from the error example:
        (error.status(), error.reason()).into_response()
    }
}

// You can then alias the HttpResult type
pub type MyHttpResult<T> = HttpResult<T, CustomErrorResponse>;

crate 功能

默认功能是 ["log", "hide-anyhow"]

功能 描述
log 使用log::error!创建的错误记录
anyhow 添加了对处理anyhow错误类型的支持
hide-anyhow 在HTTP响应中将anyhow错误消息替换为通用服务器错误消息

依赖

~1.6–2.4MB
~47K SLoC