mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-28 09:42:40 +01:00
allow to use castom error handler for json extractor
This commit is contained in:
parent
333b4f57d3
commit
5140fea8d1
37
src/error.rs
37
src/error.rs
@ -1,4 +1,5 @@
|
|||||||
//! Error and Result module
|
//! Error and Result module
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
use std::str::Utf8Error;
|
use std::str::Utf8Error;
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
@ -545,18 +546,31 @@ impl From<UrlParseError> for UrlGenerationError {
|
|||||||
/// ```
|
/// ```
|
||||||
pub struct InternalError<T> {
|
pub struct InternalError<T> {
|
||||||
cause: T,
|
cause: T,
|
||||||
status: StatusCode,
|
status: InternalErrorType,
|
||||||
backtrace: Backtrace,
|
backtrace: Backtrace,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T> Sync for InternalError<T> {}
|
unsafe impl<T> Sync for InternalError<T> {}
|
||||||
unsafe impl<T> Send for InternalError<T> {}
|
unsafe impl<T> Send for InternalError<T> {}
|
||||||
|
|
||||||
|
enum InternalErrorType {
|
||||||
|
Status(StatusCode),
|
||||||
|
Response(RefCell<Option<HttpResponse>>),
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> InternalError<T> {
|
impl<T> InternalError<T> {
|
||||||
pub fn new(cause: T, status: StatusCode) -> Self {
|
pub fn new(cause: T, status: StatusCode) -> Self {
|
||||||
InternalError {
|
InternalError {
|
||||||
cause,
|
cause,
|
||||||
status,
|
status: InternalErrorType::Status(status),
|
||||||
|
backtrace: Backtrace::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_response(cause: T, response: HttpResponse) -> Self {
|
||||||
|
InternalError {
|
||||||
|
cause,
|
||||||
|
status: InternalErrorType::Response(RefCell::new(Some(response))),
|
||||||
backtrace: Backtrace::new(),
|
backtrace: Backtrace::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -594,7 +608,16 @@ where
|
|||||||
T: Send + Sync + fmt::Debug + 'static,
|
T: Send + Sync + fmt::Debug + 'static,
|
||||||
{
|
{
|
||||||
fn error_response(&self) -> HttpResponse {
|
fn error_response(&self) -> HttpResponse {
|
||||||
HttpResponse::new(self.status)
|
match self.status {
|
||||||
|
InternalErrorType::Status(st) => HttpResponse::new(st),
|
||||||
|
InternalErrorType::Response(ref resp) => {
|
||||||
|
if let Some(resp) = resp.borrow_mut().take() {
|
||||||
|
resp
|
||||||
|
} else {
|
||||||
|
HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -859,4 +882,12 @@ mod tests {
|
|||||||
_ => env::remove_var(NAME),
|
_ => env::remove_var(NAME),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_internal_error() {
|
||||||
|
let err = InternalError::from_response(
|
||||||
|
ExpectError::Encoding, HttpResponse::Ok().into());
|
||||||
|
let resp: HttpResponse = err.error_response();
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,11 +118,12 @@ pub trait HttpMessage {
|
|||||||
/// # extern crate actix_web;
|
/// # extern crate actix_web;
|
||||||
/// # extern crate futures;
|
/// # extern crate futures;
|
||||||
/// # #[macro_use] extern crate serde_derive;
|
/// # #[macro_use] extern crate serde_derive;
|
||||||
/// use actix_web::*;
|
|
||||||
/// use bytes::Bytes;
|
/// use bytes::Bytes;
|
||||||
/// use futures::future::Future;
|
/// use futures::future::Future;
|
||||||
|
/// use actix_web::{HttpMessage, HttpRequest, HttpResponse,
|
||||||
|
/// FutureResponse, AsyncResponder};
|
||||||
///
|
///
|
||||||
/// fn index(mut req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
|
/// fn index(mut req: HttpRequest) -> FutureResponse<HttpResponse> {
|
||||||
/// req.body() // <- get Body future
|
/// req.body() // <- get Body future
|
||||||
/// .limit(1024) // <- change max size of the body to a 1kb
|
/// .limit(1024) // <- change max size of the body to a 1kb
|
||||||
/// .from_err()
|
/// .from_err()
|
||||||
|
36
src/json.rs
36
src/json.rs
@ -2,6 +2,7 @@ use bytes::{Bytes, BytesMut};
|
|||||||
use futures::{Future, Poll, Stream};
|
use futures::{Future, Poll, Stream};
|
||||||
use http::header::CONTENT_LENGTH;
|
use http::header::CONTENT_LENGTH;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use mime;
|
use mime;
|
||||||
@ -131,15 +132,17 @@ where
|
|||||||
T: DeserializeOwned + 'static,
|
T: DeserializeOwned + 'static,
|
||||||
S: 'static,
|
S: 'static,
|
||||||
{
|
{
|
||||||
type Config = JsonConfig;
|
type Config = JsonConfig<S>;
|
||||||
type Result = Box<Future<Item = Self, Error = Error>>;
|
type Result = Box<Future<Item = Self, Error = Error>>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||||
|
let req = req.clone();
|
||||||
|
let err = Rc::clone(&cfg.ehandler);
|
||||||
Box::new(
|
Box::new(
|
||||||
JsonBody::new(req.clone())
|
JsonBody::new(req.clone())
|
||||||
.limit(cfg.limit)
|
.limit(cfg.limit)
|
||||||
.from_err()
|
.map_err(move |e| (*err)(e, req))
|
||||||
.map(Json),
|
.map(Json),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -150,7 +153,7 @@ where
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
/// # extern crate actix_web;
|
||||||
/// #[macro_use] extern crate serde_derive;
|
/// #[macro_use] extern crate serde_derive;
|
||||||
/// use actix_web::{App, Json, Result, http};
|
/// use actix_web::{App, Json, HttpResponse, Result, http, error};
|
||||||
///
|
///
|
||||||
/// #[derive(Deserialize)]
|
/// #[derive(Deserialize)]
|
||||||
/// struct Info {
|
/// struct Info {
|
||||||
@ -167,25 +170,40 @@ where
|
|||||||
/// "/index.html", |r| {
|
/// "/index.html", |r| {
|
||||||
/// r.method(http::Method::POST)
|
/// r.method(http::Method::POST)
|
||||||
/// .with(index)
|
/// .with(index)
|
||||||
/// .limit(4096);} // <- change json extractor configuration
|
/// .limit(4096) // <- change json extractor configuration
|
||||||
/// );
|
/// .error_handler(|err, req| { // <- create custom error response
|
||||||
|
/// error::InternalError::from_response(
|
||||||
|
/// err, HttpResponse::Conflict().finish()).into()
|
||||||
|
/// });
|
||||||
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct JsonConfig {
|
pub struct JsonConfig<S> {
|
||||||
limit: usize,
|
limit: usize,
|
||||||
|
ehandler: Rc<Fn(JsonPayloadError, HttpRequest<S>) -> Error>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JsonConfig {
|
impl<S> JsonConfig<S> {
|
||||||
/// Change max size of payload. By default max size is 256Kb
|
/// Change max size of payload. By default max size is 256Kb
|
||||||
pub fn limit(&mut self, limit: usize) -> &mut Self {
|
pub fn limit(&mut self, limit: usize) -> &mut Self {
|
||||||
self.limit = limit;
|
self.limit = limit;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set custom error handler
|
||||||
|
pub fn error_handler<F>(&mut self, f: F) -> &mut Self
|
||||||
|
where
|
||||||
|
F: Fn(JsonPayloadError, HttpRequest<S>) -> Error + 'static
|
||||||
|
{
|
||||||
|
self.ehandler = Rc::new(f);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for JsonConfig {
|
impl<S> Default for JsonConfig<S> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
JsonConfig { limit: 262_144 }
|
JsonConfig { limit: 262_144,
|
||||||
|
ehandler: Rc::new(|e, _| e.into()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user