mirror of
https://github.com/actix/examples
synced 2025-05-11 07:52:57 +02:00
Merge pull request #1075 from peiqing6888/improve-error-handling
feat: improve error handling example - Add structured error responses…
This commit is contained in:
commit
0453d331ef
@ -10,3 +10,5 @@ derive_more = { workspace = true, features = ["display"] }
|
||||
env_logger.workspace = true
|
||||
log.workspace = true
|
||||
rand.workspace = true
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json.workspace = true
|
||||
|
@ -18,19 +18,28 @@ use rand::{
|
||||
Rng,
|
||||
distr::{Distribution, StandardUniform},
|
||||
};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, Display)]
|
||||
#[derive(Debug, Display, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum CustomError {
|
||||
#[display("Custom Error 1")]
|
||||
#[display("Access forbidden: insufficient permissions")]
|
||||
CustomOne,
|
||||
#[display("Custom Error 2")]
|
||||
#[display("Authentication required")]
|
||||
CustomTwo,
|
||||
#[display("Custom Error 3")]
|
||||
#[display("Internal server error occurred")]
|
||||
CustomThree,
|
||||
#[display("Custom Error 4")]
|
||||
#[display("Invalid request parameters")]
|
||||
CustomFour,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ErrorResponse {
|
||||
code: u16,
|
||||
message: String,
|
||||
error_type: String,
|
||||
}
|
||||
|
||||
impl Distribution<CustomError> for StandardUniform {
|
||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> CustomError {
|
||||
match rng.random_range(0..4) {
|
||||
@ -45,46 +54,57 @@ impl Distribution<CustomError> for StandardUniform {
|
||||
/// Actix Web uses `ResponseError` for conversion of errors to a response
|
||||
impl ResponseError for CustomError {
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
match self {
|
||||
let (status_code, error_msg) = match self {
|
||||
CustomError::CustomOne => {
|
||||
println!("do some stuff related to CustomOne error");
|
||||
HttpResponse::Forbidden().finish()
|
||||
log::error!("Forbidden error: {}", self);
|
||||
(403, self.to_string())
|
||||
}
|
||||
|
||||
CustomError::CustomTwo => {
|
||||
println!("do some stuff related to CustomTwo error");
|
||||
HttpResponse::Unauthorized().finish()
|
||||
log::error!("Unauthorized error: {}", self);
|
||||
(401, self.to_string())
|
||||
}
|
||||
|
||||
CustomError::CustomThree => {
|
||||
println!("do some stuff related to CustomThree error");
|
||||
HttpResponse::InternalServerError().finish()
|
||||
log::error!("Internal server error: {}", self);
|
||||
(500, self.to_string())
|
||||
}
|
||||
CustomError::CustomFour => {
|
||||
log::error!("Bad request error: {}", self);
|
||||
(400, self.to_string())
|
||||
}
|
||||
};
|
||||
|
||||
_ => {
|
||||
println!("do some stuff related to CustomFour error");
|
||||
HttpResponse::BadRequest().finish()
|
||||
}
|
||||
}
|
||||
let error_response = ErrorResponse {
|
||||
code: status_code,
|
||||
message: error_msg,
|
||||
error_type: format!("{:?}", self),
|
||||
};
|
||||
|
||||
HttpResponse::build(actix_web::http::StatusCode::from_u16(status_code).unwrap())
|
||||
.json(error_response)
|
||||
}
|
||||
}
|
||||
|
||||
/// randomly returns either () or one of the 4 CustomError variants
|
||||
async fn do_something_random() -> Result<(), CustomError> {
|
||||
let mut rng = rand::rng();
|
||||
|
||||
// 20% chance that () will be returned by this function
|
||||
if rng.random_bool(2.0 / 10.0) {
|
||||
// 20% chance of success
|
||||
const SUCCESS_PROBABILITY: f64 = 0.2;
|
||||
if rng.random_bool(SUCCESS_PROBABILITY) {
|
||||
log::info!("Random operation succeeded");
|
||||
Ok(())
|
||||
} else {
|
||||
Err(rand::random::<CustomError>())
|
||||
let error = rand::random::<CustomError>();
|
||||
log::warn!("Random operation failed with error: {}", error);
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
|
||||
async fn do_something() -> Result<HttpResponse, Error> {
|
||||
do_something_random().await?;
|
||||
|
||||
Ok(HttpResponse::Ok().body("Nothing interesting happened. Try again."))
|
||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
||||
"status": "success",
|
||||
"message": "Nothing interesting happened. Try again."
|
||||
})))
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
|
Loading…
x
Reference in New Issue
Block a user