domains / / tokio-rs/axum
Structure errors for safety
Create specific error types with appropriate status codes while ensuring sensitive details are logged but not exposed to clients. Follow guidelines for defining specific error types, implementing proper status codes, logging detailed errors internally, and returning sanitized error messages to clients.
Create specific error types with appropriate status codes while ensuring sensitive details are logged but not exposed to clients. Follow these guidelines:
- Define specific error types instead of using generic ones
- Implement proper status codes for each error variant
- Log detailed errors internally
- Return sanitized error messages to clients
Example:
#[derive(Debug, Error)]
pub enum ApiError {
#[error("Invalid input provided")]
ValidationError(#[from] JsonRejection),
#[error("Internal server error")]
InternalError(#[source] anyhow::Error),
}
impl IntoResponse for ApiError {
fn into_response(self) -> Response {
let status = match &self {
Self::ValidationError(_) => StatusCode::UNPROCESSABLE_ENTITY,
Self::InternalError(_) => StatusCode::INTERNAL_SERVER_ERROR,
};
// Log detailed error internally
tracing::error!("{:#}", self);
// Return sanitized response to client
let body = Json(json!({
"error": self.to_string() // Uses the #[error] messages
}));
(status, body).into_response()
}
}