< 返回版块

duan-zhou 发表于 2024-11-20 13:09

如题,两个例子都要自己实现IntoResponse

第一例子用anyhow, 似乎所有的错误都只能用一个状态码

// Make our own error that wraps `anyhow::Error`.
struct AppError(anyhow::Error);

// Tell axum how to convert `AppError` into a response.
impl IntoResponse for AppError {
    fn into_response(self) -> Response {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Something went wrong: {}", self.0),
        )
            .into_response()
    }
}

第二个例子自定义错误类型,但是不能明了的看到用了什么状态码,要是thiserror这个库的宏有个status属性并自动实现IntoResponse感觉就不错

// The kinds of errors we can hit in our application.
enum AppError {
    // The request body contained invalid JSON
    JsonRejection(JsonRejection),
    // Some error from a third party library we're using
    TimeError(time_library::Error),
}

// Tell axum how `AppError` should be converted into a response.
//
// This is also a convenient place to log errors.
impl IntoResponse for AppError {
    fn into_response(self) -> Response {
        unimplemented!()
    }
}

评论区

写评论
flmn 2024-11-21 10:01

供参考:

#[derive(Debug, Clone, thiserror::Error)]
pub enum AppError {
    #[error("{0}")]
    AlreadyExists(String),

    #[error("认证失败")]
    AuthenticationFailed,

    #[error("需要认证")]
    AuthenticationRequired,

    #[error("{0}")]
    _General(String),

    #[error("服务器内部错误")]
    Internal(String),

    #[error("{0}")]
    InvalidArgument(String),

    #[error("{0}")]
    NotFound(String),

    #[error("{0}")]
    _PermissionDenied(String),

    #[error("{0}")]
    SerialError(String),
}

pub type AppResult<T> = Result<T, AppError>;

impl IntoResponse for AppError {
    fn into_response(self) -> Response {
        let (status, code) = match &self {
            AppError::AlreadyExists(_) => (StatusCode::OK, "AlreadyExists"),
            AppError::AuthenticationFailed => (StatusCode::OK, "AuthenticationFailed"),
            AppError::AuthenticationRequired => {
                (StatusCode::UNAUTHORIZED, "AuthenticationRequired")
            }
            AppError::_General(_) => (StatusCode::OK, "General"),
            AppError::Internal(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Internal"),
            AppError::InvalidArgument(_) => (StatusCode::OK, "InvalidArgument"),
            AppError::NotFound(_) => (StatusCode::NOT_FOUND, "NotFound"),
            AppError::_PermissionDenied(_) => (StatusCode::FORBIDDEN, "PermissionDenied"),
            AppError::SerialError(_) => (StatusCode::OK, "SerialError"),
        };

        let message = match &self {
            AppError::Internal(message) => {
                // log the internal error
                error!("Internal error: {}", message);

                self.to_string()
            }
            _ => self.to_string(),
        };

        (status, ApiResult::<()>::error(code.to_string(), message)).into_response()
    }
}
1 共 1 条评论, 1 页