2017-12-09 00:25:37 +01:00
|
|
|
# Errors
|
|
|
|
|
2018-03-28 22:16:01 +02:00
|
|
|
Actix uses [`Error` type](../actix_web/error/struct.Error.html)
|
|
|
|
and [`ResponseError` trait](../actix_web/error/trait.ResponseError.html)
|
2017-12-09 00:25:37 +01:00
|
|
|
for handling handler's errors.
|
2018-03-28 22:16:01 +02:00
|
|
|
Any error that implements the `ResponseError` trait can be returned as an error value.
|
|
|
|
*Handler* can return an *Result* object; actix by default provides
|
|
|
|
`Responder` implementation for compatible result types. Here is the implementation
|
2017-12-09 00:25:37 +01:00
|
|
|
definition:
|
|
|
|
|
|
|
|
```rust,ignore
|
2017-12-14 18:43:42 +01:00
|
|
|
impl<T: Responder, E: Into<Error>> Responder for Result<T, E>
|
2017-12-09 00:25:37 +01:00
|
|
|
```
|
|
|
|
|
2018-03-28 22:16:01 +02:00
|
|
|
And any error that implements `ResponseError` can be converted into an `Error` object.
|
|
|
|
For example, if the *handler* function returns `io::Error`, it would be converted
|
|
|
|
into an `HttpInternalServerError` response. Implementation for `io::Error` is provided
|
2017-12-09 00:25:37 +01:00
|
|
|
by default.
|
|
|
|
|
|
|
|
```rust
|
|
|
|
# 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() {
|
2017-12-11 23:16:29 +01:00
|
|
|
# Application::new()
|
2017-12-09 00:25:37 +01:00
|
|
|
# .resource(r"/a/index.html", |r| r.f(index))
|
|
|
|
# .finish();
|
|
|
|
# }
|
|
|
|
```
|
|
|
|
|
|
|
|
## Custom error response
|
|
|
|
|
2018-03-28 22:16:01 +02:00
|
|
|
To add support for custom errors, all we need to do is just implement the `ResponseError` trait
|
|
|
|
for the custom error type. The `ResponseError` trait has a default implementation
|
|
|
|
for the `error_response()` method: it generates a *500* response.
|
2017-12-09 00:25:37 +01:00
|
|
|
|
|
|
|
```rust
|
|
|
|
# extern crate actix_web;
|
|
|
|
#[macro_use] extern crate failure;
|
|
|
|
use actix_web::*;
|
|
|
|
|
|
|
|
#[derive(Fail, Debug)]
|
|
|
|
#[fail(display="my error")]
|
|
|
|
struct MyError {
|
|
|
|
name: &'static str
|
|
|
|
}
|
|
|
|
|
2017-12-21 08:27:30 +01:00
|
|
|
/// Use default implementation for `error_response()` method
|
2017-12-09 00:25:37 +01:00
|
|
|
impl error::ResponseError for MyError {}
|
|
|
|
|
|
|
|
fn index(req: HttpRequest) -> Result<&'static str, MyError> {
|
|
|
|
Err(MyError{name: "test"})
|
|
|
|
}
|
|
|
|
#
|
|
|
|
# fn main() {
|
2017-12-11 23:16:29 +01:00
|
|
|
# Application::new()
|
2017-12-09 00:25:37 +01:00
|
|
|
# .resource(r"/a/index.html", |r| r.f(index))
|
|
|
|
# .finish();
|
|
|
|
# }
|
|
|
|
```
|
|
|
|
|
2018-03-28 22:16:01 +02:00
|
|
|
In this example the *index* handler always returns a *500* response. But it is easy
|
|
|
|
to return different responses for different types of errors.
|
2017-12-09 00:25:37 +01:00
|
|
|
|
|
|
|
```rust
|
|
|
|
# extern crate actix_web;
|
|
|
|
#[macro_use] extern crate failure;
|
2018-03-31 02:31:18 +02:00
|
|
|
use actix_web::{Application, Body, HttpRequest, HttpResponse, http, error};
|
2017-12-09 00:25:37 +01:00
|
|
|
|
|
|
|
#[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(
|
2018-03-31 02:31:18 +02:00
|
|
|
http::StatusCode::INTERNAL_SERVER_ERROR, Body::Empty),
|
2017-12-09 00:25:37 +01:00
|
|
|
MyError::BadClientData => HttpResponse::new(
|
2018-03-31 02:31:18 +02:00
|
|
|
http::StatusCode::BAD_REQUEST, Body::Empty),
|
2017-12-09 00:25:37 +01:00
|
|
|
MyError::Timeout => HttpResponse::new(
|
2018-03-31 02:31:18 +02:00
|
|
|
http::StatusCode::GATEWAY_TIMEOUT, Body::Empty),
|
2017-12-09 00:25:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn index(req: HttpRequest) -> Result<&'static str, MyError> {
|
|
|
|
Err(MyError::BadClientData)
|
|
|
|
}
|
|
|
|
#
|
|
|
|
# fn main() {
|
2017-12-11 23:16:29 +01:00
|
|
|
# Application::new()
|
2017-12-09 00:25:37 +01:00
|
|
|
# .resource(r"/a/index.html", |r| r.f(index))
|
|
|
|
# .finish();
|
|
|
|
# }
|
|
|
|
```
|
|
|
|
|
|
|
|
## Error helpers
|
|
|
|
|
2018-03-28 22:16:01 +02:00
|
|
|
Actix provides a set of error helper types. It is possible to use them for generating
|
2018-03-27 03:18:38 +02:00
|
|
|
specific error responses. We can use helper types for the first example with custom error.
|
2017-12-09 00:25:37 +01:00
|
|
|
|
|
|
|
```rust
|
|
|
|
# extern crate actix_web;
|
|
|
|
#[macro_use] extern crate failure;
|
|
|
|
use actix_web::*;
|
|
|
|
|
2018-01-21 07:02:42 +01:00
|
|
|
#[derive(Debug)]
|
2017-12-09 00:25:37 +01:00
|
|
|
struct MyError {
|
|
|
|
name: &'static str
|
|
|
|
}
|
|
|
|
|
|
|
|
fn index(req: HttpRequest) -> Result<&'static str> {
|
|
|
|
let result: Result<&'static str, MyError> = Err(MyError{name: "test"});
|
2018-03-28 22:16:01 +02:00
|
|
|
|
2018-03-22 05:02:04 +01:00
|
|
|
Ok(result.map_err(|e| error::ErrorBadRequest(e))?)
|
2017-12-09 00:25:37 +01:00
|
|
|
}
|
|
|
|
# fn main() {
|
2017-12-11 23:16:29 +01:00
|
|
|
# Application::new()
|
2017-12-09 00:25:37 +01:00
|
|
|
# .resource(r"/a/index.html", |r| r.f(index))
|
|
|
|
# .finish();
|
|
|
|
# }
|
|
|
|
```
|
|
|
|
|
2018-03-28 22:16:01 +02:00
|
|
|
In this example, a *BAD REQUEST* response is generated for the `MyError` error.
|
2018-01-21 05:21:01 +01:00
|
|
|
|
|
|
|
## Error logging
|
|
|
|
|
2018-03-28 22:16:01 +02:00
|
|
|
Actix logs all errors with the log level `WARN`. If log level set to `DEBUG`
|
|
|
|
and `RUST_BACKTRACE` is enabled, the backtrace gets logged. The Error type uses
|
|
|
|
the cause's error backtrace if available. If the underlying failure does not provide
|
2018-01-21 05:21:01 +01:00
|
|
|
a backtrace, a new backtrace is constructed pointing to that conversion point
|
|
|
|
(rather than the origin of the error). This construction only happens if there
|
2018-03-28 22:16:01 +02:00
|
|
|
is no underlying backtrace; if it does have a backtrace, no new backtrace is constructed.
|
2018-01-21 05:21:01 +01:00
|
|
|
|
2018-03-28 22:16:01 +02:00
|
|
|
You can enable backtrace and debug logging with following command:
|
2018-01-21 05:21:01 +01:00
|
|
|
|
|
|
|
```
|
|
|
|
>> RUST_BACKTRACE=1 RUST_LOG=actix_web=debug cargo run
|
|
|
|
```
|