2018-08-07 18:03:16 +02:00
|
|
|
/*
|
2019-03-10 03:03:09 +01:00
|
|
|
The goal of this example is to show how to propagate a custom error type,
|
|
|
|
to a web handler that will evaluate the type of error that
|
2018-08-07 18:03:16 +02:00
|
|
|
was raised and return an appropriate HTTPResponse.
|
|
|
|
|
|
|
|
This example uses a 50/50 chance of returning 200 Ok, otherwise one of four possible
|
2019-03-10 03:03:09 +01:00
|
|
|
http errors will be chosen, each with an equal chance of being selected:
|
2018-08-07 18:03:16 +02:00
|
|
|
1. 403 Forbidden
|
|
|
|
2. 401 Unauthorized
|
|
|
|
3. 500 InternalServerError
|
|
|
|
4. 400 BadRequest
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2019-03-10 03:03:09 +01:00
|
|
|
use actix_web::{web, App, Error, HttpResponse, HttpServer, ResponseError};
|
|
|
|
use derive_more::Display; // naming it clearly for illustration purposes
|
|
|
|
use rand::{
|
|
|
|
distributions::{Distribution, Standard},
|
|
|
|
thread_rng, Rng,
|
2018-08-07 18:03:16 +02:00
|
|
|
};
|
|
|
|
|
2019-03-10 03:03:09 +01:00
|
|
|
#[derive(Debug, Display)]
|
2018-08-07 18:03:16 +02:00
|
|
|
pub enum CustomError {
|
2019-03-10 03:03:09 +01:00
|
|
|
#[display(fmt = "Custom Error 1")]
|
2018-08-07 18:03:16 +02:00
|
|
|
CustomOne,
|
2019-03-10 03:03:09 +01:00
|
|
|
#[display(fmt = "Custom Error 2")]
|
2018-08-07 18:03:16 +02:00
|
|
|
CustomTwo,
|
2019-03-10 03:03:09 +01:00
|
|
|
#[display(fmt = "Custom Error 3")]
|
2018-08-07 18:03:16 +02:00
|
|
|
CustomThree,
|
2019-03-10 03:03:09 +01:00
|
|
|
#[display(fmt = "Custom Error 4")]
|
|
|
|
CustomFour,
|
2018-08-07 18:03:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Distribution<CustomError> for Standard {
|
|
|
|
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> CustomError {
|
|
|
|
match rng.gen_range(0, 4) {
|
|
|
|
0 => CustomError::CustomOne,
|
|
|
|
1 => CustomError::CustomTwo,
|
|
|
|
2 => CustomError::CustomThree,
|
2019-03-10 03:03:09 +01:00
|
|
|
_ => CustomError::CustomFour,
|
2018-08-07 18:03:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-10 03:03:09 +01:00
|
|
|
/// Actix web uses `ResponseError` for conversion of errors to a response
|
2018-08-07 18:03:16 +02:00
|
|
|
impl ResponseError for CustomError {
|
|
|
|
fn error_response(&self) -> HttpResponse {
|
2019-03-10 03:03:09 +01:00
|
|
|
match self {
|
|
|
|
CustomError::CustomOne => {
|
|
|
|
println!("do some stuff related to CustomOne error");
|
|
|
|
HttpResponse::Forbidden().finish()
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomError::CustomTwo => {
|
|
|
|
println!("do some stuff related to CustomTwo error");
|
|
|
|
HttpResponse::Unauthorized().finish()
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomError::CustomThree => {
|
|
|
|
println!("do some stuff related to CustomThree error");
|
|
|
|
HttpResponse::InternalServerError().finish()
|
|
|
|
}
|
|
|
|
|
|
|
|
_ => {
|
|
|
|
println!("do some stuff related to CustomFour error");
|
|
|
|
HttpResponse::BadRequest().finish()
|
|
|
|
}
|
|
|
|
}
|
2018-08-07 18:03:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// randomly returns either () or one of the 4 CustomError variants
|
2019-12-07 18:59:24 +01:00
|
|
|
async fn do_something_random() -> Result<(), CustomError> {
|
2018-08-07 18:03:16 +02:00
|
|
|
let mut rng = thread_rng();
|
|
|
|
|
|
|
|
// 20% chance that () will be returned by this function
|
2019-03-10 03:03:09 +01:00
|
|
|
if rng.gen_bool(2.0 / 10.0) {
|
2019-12-07 18:59:24 +01:00
|
|
|
Ok(())
|
2019-03-10 03:03:09 +01:00
|
|
|
} else {
|
2019-12-07 18:59:24 +01:00
|
|
|
Err(rand::random::<CustomError>())
|
2018-08-07 18:03:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-07 18:59:24 +01:00
|
|
|
async fn do_something() -> Result<HttpResponse, Error> {
|
|
|
|
do_something_random().await?;
|
|
|
|
|
|
|
|
Ok(HttpResponse::Ok().body("Nothing interesting happened. Try again."))
|
2018-08-07 18:03:16 +02:00
|
|
|
}
|
|
|
|
|
2019-12-07 18:59:24 +01:00
|
|
|
#[actix_rt::main]
|
|
|
|
async fn main() -> std::io::Result<()> {
|
2019-03-10 03:03:09 +01:00
|
|
|
std::env::set_var("RUST_LOG", "actix_web=info");
|
2018-08-07 18:03:16 +02:00
|
|
|
env_logger::init();
|
|
|
|
|
2019-03-10 03:03:09 +01:00
|
|
|
HttpServer::new(move || {
|
2019-12-07 18:59:24 +01:00
|
|
|
App::new()
|
|
|
|
.service(web::resource("/something").route(web::get().to(do_something)))
|
2019-03-10 03:03:09 +01:00
|
|
|
})
|
|
|
|
.bind("127.0.0.1:8088")?
|
2019-12-07 18:59:24 +01:00
|
|
|
.start()
|
|
|
|
.await
|
2018-08-07 18:03:16 +02:00
|
|
|
}
|