mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-24 08:22:59 +01:00
add ErrorHandlers middleware
This commit is contained in:
parent
d292c5023f
commit
3b93bff602
@ -210,3 +210,37 @@ fn main() {
|
|||||||
# let _ = sys.run();
|
# let _ = sys.run();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Error handlers
|
||||||
|
|
||||||
|
`ErrorHandlers` middleware allows to provide custom handlers for responses.
|
||||||
|
|
||||||
|
You can use `ErrorHandlers::handler()` method to register a custom error handler
|
||||||
|
for specific status code. You can modify existing response or create completly new
|
||||||
|
one. Error handler can return response immediately or return future that resolves
|
||||||
|
to a response.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
# extern crate actix_web;
|
||||||
|
use actix_web::{
|
||||||
|
App, HttpRequest, HttpResponse, Result,
|
||||||
|
http, middleware::Response, middleware::ErrorHandlers};
|
||||||
|
|
||||||
|
fn render_500<S>(_: &mut HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||||
|
let mut builder = resp.into_builder();
|
||||||
|
builder.header(http::header::CONTENT_TYPE, "application/json");
|
||||||
|
Ok(Response::Done(builder.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let app = App::new()
|
||||||
|
.middleware(
|
||||||
|
ErrorHandlers::new()
|
||||||
|
.handler(http::StatusCode::INTERNAL_SERVER_ERROR, render_500))
|
||||||
|
.resource("/test", |r| {
|
||||||
|
r.method(http::Method::GET).f(|_| HttpResponse::Ok());
|
||||||
|
r.method(http::Method::HEAD).f(|_| HttpResponse::MethodNotAllowed());
|
||||||
|
})
|
||||||
|
.finish();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
115
src/middleware/errhandlers.rs
Normal file
115
src/middleware/errhandlers.rs
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use error::Result;
|
||||||
|
use http::StatusCode;
|
||||||
|
use httprequest::HttpRequest;
|
||||||
|
use httpresponse::HttpResponse;
|
||||||
|
use middleware::{Middleware, Response};
|
||||||
|
|
||||||
|
|
||||||
|
type ErrorHandler<S> = Fn(&mut HttpRequest<S>, HttpResponse) -> Result<Response>;
|
||||||
|
|
||||||
|
/// `Middleware` for allowing custom handlers for responses.
|
||||||
|
///
|
||||||
|
/// You can use `ErrorHandlers::handler()` method to register a custom error handler
|
||||||
|
/// for specific status code. You can modify existing response or create completly new
|
||||||
|
/// one.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # extern crate actix_web;
|
||||||
|
/// use actix_web::{
|
||||||
|
/// App, HttpRequest, HttpResponse, Result,
|
||||||
|
/// http, middleware::Response, middleware::ErrorHandlers};
|
||||||
|
///
|
||||||
|
/// fn render_500<S>(_: &mut HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||||
|
/// let mut builder = resp.into_builder();
|
||||||
|
/// builder.header(http::header::CONTENT_TYPE, "application/json");
|
||||||
|
/// Ok(Response::Done(builder.into()))
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// let app = App::new()
|
||||||
|
/// .middleware(
|
||||||
|
/// ErrorHandlers::new()
|
||||||
|
/// .handler(http::StatusCode::INTERNAL_SERVER_ERROR, render_500))
|
||||||
|
/// .resource("/test", |r| {
|
||||||
|
/// r.method(http::Method::GET).f(|_| HttpResponse::Ok());
|
||||||
|
/// r.method(http::Method::HEAD).f(|_| HttpResponse::MethodNotAllowed());
|
||||||
|
/// })
|
||||||
|
/// .finish();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub struct ErrorHandlers<S> {
|
||||||
|
handlers: HashMap<StatusCode, Box<ErrorHandler<S>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> Default for ErrorHandlers<S> {
|
||||||
|
fn default() -> Self {
|
||||||
|
ErrorHandlers {
|
||||||
|
handlers: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> ErrorHandlers<S> {
|
||||||
|
|
||||||
|
/// Construct new `ErrorHandlers` instance
|
||||||
|
pub fn new() -> Self {
|
||||||
|
ErrorHandlers::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register error handler for specified status code
|
||||||
|
pub fn handler<F>(mut self, status: StatusCode, handler: F) -> Self
|
||||||
|
where F: Fn(&mut HttpRequest<S>, HttpResponse) -> Result<Response> + 'static
|
||||||
|
{
|
||||||
|
self.handlers.insert(status, Box::new(handler));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: 'static> Middleware<S> for ErrorHandlers<S> {
|
||||||
|
|
||||||
|
fn response(&self, req: &mut HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||||
|
if let Some(handler) = self.handlers.get(&resp.status()) {
|
||||||
|
handler(req, resp)
|
||||||
|
} else {
|
||||||
|
Ok(Response::Done(resp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use http::StatusCode;
|
||||||
|
use http::header::CONTENT_TYPE;
|
||||||
|
|
||||||
|
fn render_500<S>(_: &mut HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||||
|
let mut builder = resp.into_builder();
|
||||||
|
builder.header(CONTENT_TYPE, "0001");
|
||||||
|
Ok(Response::Done(builder.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_handler() {
|
||||||
|
let mw = ErrorHandlers::new()
|
||||||
|
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500);
|
||||||
|
|
||||||
|
let mut req = HttpRequest::default();
|
||||||
|
let resp = HttpResponse::InternalServerError().finish();
|
||||||
|
let resp = match mw.response(&mut req, resp) {
|
||||||
|
Ok(Response::Done(resp)) => resp,
|
||||||
|
_ => panic!(),
|
||||||
|
};
|
||||||
|
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
|
||||||
|
|
||||||
|
let resp = HttpResponse::Ok().finish();
|
||||||
|
let resp = match mw.response(&mut req, resp) {
|
||||||
|
Ok(Response::Done(resp)) => resp,
|
||||||
|
_ => panic!(),
|
||||||
|
};
|
||||||
|
assert!(!resp.headers().contains_key(CONTENT_TYPE));
|
||||||
|
}
|
||||||
|
}
|
@ -10,9 +10,11 @@ mod logger;
|
|||||||
#[cfg(feature = "session")]
|
#[cfg(feature = "session")]
|
||||||
mod session;
|
mod session;
|
||||||
mod defaultheaders;
|
mod defaultheaders;
|
||||||
|
mod errhandlers;
|
||||||
pub mod cors;
|
pub mod cors;
|
||||||
pub mod csrf;
|
pub mod csrf;
|
||||||
pub use self::logger::Logger;
|
pub use self::logger::Logger;
|
||||||
|
pub use self::errhandlers::ErrorHandlers;
|
||||||
pub use self::defaultheaders::{DefaultHeaders, DefaultHeadersBuilder};
|
pub use self::defaultheaders::{DefaultHeaders, DefaultHeadersBuilder};
|
||||||
|
|
||||||
#[cfg(feature = "session")]
|
#[cfg(feature = "session")]
|
||||||
|
Loading…
Reference in New Issue
Block a user