1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-24 16:02:59 +01:00
actix-extras/guide/src/qs_4_5.md

3.4 KiB

Errors

Actix uses Error type and ResponseError trait for handling handler's errors. Any error that implements ResponseError trait can be returned as error value. Handler can return Result object, actix by default provides FromRequest implemenation for compatible result object. Here is implementation definition:

impl<T: FromRequest, E: Into<Error>> FromRequest for Result<T, E>

And any error that implements ResponseError can be converted into Error object. For example if handler function returns io::Error, it would be converted into HTTPInternalServerError response. Implementation for io::Error is provided by default.

# extern crate actix_web;
# use actix_web::*;
use std::io;

fn index(req: HttpRequest) -> io::Result<fs::NamedFile> {
    Ok(fs::NamedFile::open("static/index.html")?)
}
#
# fn main() {
#     Application::new()
#         .resource(r"/a/index.html", |r| r.f(index))
#         .finish();
# }

Custom error response

To add support for custom errors all we need to do just implement ResponseError trait. ResponseError trait has default implementation for error_response() method, it generates 500 response.

# extern crate actix_web;
#[macro_use] extern crate failure;
use actix_web::*;

#[derive(Fail, Debug)]
#[fail(display="my error")]
struct MyError {
   name: &'static str
}

impl error::ResponseError for MyError {}

fn index(req: HttpRequest) -> Result<&'static str, MyError> {
    Err(MyError{name: "test"})
}
#
# fn main() {
#     Application::new()
#         .resource(r"/a/index.html", |r| r.f(index))
#         .finish();
# }

In this example index handler will always return 500 response. But it is easy to return different responses.

# extern crate actix_web;
#[macro_use] extern crate failure;
use actix_web::*;

#[derive(Fail, Debug)]
enum MyError {
   #[fail(display="internal error")]
   InternalError,
   #[fail(display="bad request")]
   BadClientData,
   #[fail(display="timeout")]
   Timeout,
}

impl error::ResponseError for MyError {
    fn error_response(&self) -> HttpResponse {
       match *self {
          MyError::InternalError => HttpResponse::new(
              StatusCode::INTERNAL_SERVER_ERROR, Body::Empty),
          MyError::BadClientData => HttpResponse::new(
              StatusCode::BAD_REQUEST, Body::Empty),
          MyError::Timeout => HttpResponse::new(
              StatusCode::GATEWAY_TIMEOUT, Body::Empty),
       }
    }
}

fn index(req: HttpRequest) -> Result<&'static str, MyError> {
    Err(MyError::BadClientData)
}
#
# fn main() {
#     Application::new()
#         .resource(r"/a/index.html", |r| r.f(index))
#         .finish();
# }

Error helpers

Actix provides set of error helper types. It is possible to use them to generate specific error response. We can use helper types for first example with custom error.

# extern crate actix_web;
#[macro_use] extern crate failure;
use actix_web::*;

#[derive(Debug)]
struct MyError {
   name: &'static str
}

fn index(req: HttpRequest) -> Result<&'static str> {
    let result: Result<&'static str, MyError> = Err(MyError{name: "test"});
    
    Ok(result.map_err(error::ErrorBadRequest)?)
}
# fn main() {
#     Application::new()
#         .resource(r"/a/index.html", |r| r.f(index))
#         .finish();
# }

In this example BAD REQUEST response get generated for MYError error.