From 8f62837614bb76d8ecef64a789a9720496f7b6ce Mon Sep 17 00:00:00 2001 From: dowwie Date: Tue, 7 Aug 2018 12:03:16 -0400 Subject: [PATCH 1/2] added error_handling example --- Cargo.toml | 1 + error_handling/.gitignore | 2 + error_handling/Cargo.toml | 12 ++++ error_handling/README.md | 1 + error_handling/src/main.rs | 139 +++++++++++++++++++++++++++++++++++++ 5 files changed, 155 insertions(+) create mode 100644 error_handling/.gitignore create mode 100644 error_handling/Cargo.toml create mode 100644 error_handling/README.md create mode 100644 error_handling/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index fb89e0a7..17ed4eb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "cookie-auth-full", "cookie-session", "diesel", + "error_handling", "form", "hello-world", "http-proxy", diff --git a/error_handling/.gitignore b/error_handling/.gitignore new file mode 100644 index 00000000..53eaa219 --- /dev/null +++ b/error_handling/.gitignore @@ -0,0 +1,2 @@ +/target +**/*.rs.bk diff --git a/error_handling/Cargo.toml b/error_handling/Cargo.toml new file mode 100644 index 00000000..fe27b1c3 --- /dev/null +++ b/error_handling/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "error_handling" +version = "0.1.0" +authors = ["dowwie "] + +[dependencies] +actix = "0.7.3" +actix-web = "0.7.3" +failure = "0.1.2" +futures = "0.1.23" +rand = "0.5.4" +env_logger = "0.5.12" diff --git a/error_handling/README.md b/error_handling/README.md new file mode 100644 index 00000000..4c04b229 --- /dev/null +++ b/error_handling/README.md @@ -0,0 +1 @@ +This project illustrates custom error propagation through futures in actix-web diff --git a/error_handling/src/main.rs b/error_handling/src/main.rs new file mode 100644 index 00000000..6a1788f0 --- /dev/null +++ b/error_handling/src/main.rs @@ -0,0 +1,139 @@ +/* +The goal of this example is to show how to propagate a custom error type, derived +from the Fail trait, to a web handler that will evaluate the type of error that +was raised and return an appropriate HTTPResponse. + +This example uses a 50/50 chance of returning 200 Ok, otherwise one of four possible +http errors will be chosen, each with an equal chance of being selected: + 1. 403 Forbidden + 2. 401 Unauthorized + 3. 500 InternalServerError + 4. 400 BadRequest + +*/ + + +extern crate actix; +extern crate actix_web; +extern crate env_logger; +#[macro_use] extern crate failure; +extern crate futures; +extern crate rand; + + +use actix_web::{ + http::Method, server, App, AsyncResponder, Error as ActixWebError, + HttpResponse, HttpRequest +}; +use failure::Error as FailureError; // naming it clearly for illustration purposes +use futures::{ + future::{ + ok as fut_ok, + err as fut_err + }, + Future +}; +use rand::{thread_rng, Rng, distributions::{Distribution, Standard}}; + + + +#[derive(Fail, Debug)] +pub enum CustomError { + #[fail(display = "Custom Error 1")] + CustomOne, + #[fail(display = "Custom Error 2")] + CustomTwo, + #[fail(display = "Custom Error 3")] + CustomThree, + #[fail(display = "Custom Error 4")] + CustomFour +} + + +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> CustomError { + match rng.gen_range(0, 4) { + 0 => CustomError::CustomOne, + 1 => CustomError::CustomTwo, + 2 => CustomError::CustomThree, + _ => CustomError::CustomFour + } + } +} + +/* +impl ResponseError for CustomError { + fn error_response(&self) -> HttpResponse { + HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR) + } +} +*/ + + +/// randomly returns either () or one of the 4 CustomError variants +//fn do_something_random() -> impl Future, +// Error = ActixWebError> { +fn do_something_random() -> impl Future { + let mut rng = thread_rng(); + + // 20% chance that () will be returned by this function + if rng.gen_bool(2.0/10.0) { + return fut_ok(()) + } + + let err: CustomError = rand::random(); + return fut_err(err) +} + + +fn do_something(_req: HttpRequest) + -> impl Future { + + do_something_random() + .then(|result| match result { + Ok(_) => Ok(HttpResponse::Ok() + .body("Nothing interesting happened. Try again.")), + + Err(err) => match err { + CustomError::CustomOne => { + println!("do some stuff related to CustomOne error"); + Ok(HttpResponse::Forbidden().finish()) + }, + + CustomError::CustomTwo => { + println!("do some stuff related to CustomTwo error"); + Ok(HttpResponse::Unauthorized().finish()) + }, + + CustomError::CustomThree => { + println!("do some stuff related to CustomThree error"); + Ok(HttpResponse::InternalServerError().finish()) + }, + + _ => { + println!("do some stuff related to CustomFour error"); + Ok(HttpResponse::BadRequest().finish()) + } + } + }) + .responder() +} + + +fn main() { + ::std::env::set_var("RUST_LOG", "actix_web=info"); + env_logger::init(); + let sys = actix::System::new("error_handling_example"); + + server::new(move || { + App::new() + .resource("/something", |r| + r.method(Method::GET) + .with_async(do_something)) + }).bind("127.0.0.1:8088") + .unwrap() + .start(); + + println!("Started http server: 127.0.0.1:8088"); + let _ = sys.run(); +} From 026ff64cf3cd0dd7f8727b827e79a04b1491d876 Mon Sep 17 00:00:00 2001 From: dowwie Date: Tue, 7 Aug 2018 13:07:52 -0400 Subject: [PATCH 2/2] updated travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7d10d027..9bd4f006 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,6 +41,7 @@ script: cd cookie-auth-full && cargo check && cd .. cd cookie-session && cargo check && cd .. cd diesel && cargo check && cd .. + cd error_handling && cargo check && cd .. cd form && cargo check && cd .. cd hello-world && cargo check && cd .. cd http-proxy && cargo check && cd ..