mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-24 00:21:08 +01:00
Added initial support for PathConfig, allows setting custom error handler. (#903)
This commit is contained in:
parent
36e6f0cb4b
commit
13e618b128
19
src/error.rs
19
src/error.rs
@ -92,6 +92,25 @@ impl ResponseError for JsonPayloadError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A set of errors that can occur during parsing request paths
|
||||||
|
#[derive(Debug, Display, From)]
|
||||||
|
pub enum PathPayloadError {
|
||||||
|
/// Deserialize error
|
||||||
|
#[display(fmt = "Path deserialize error: {}", _0)]
|
||||||
|
Deserialize(de::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return `BadRequest` for `PathPayloadError`
|
||||||
|
impl ResponseError for PathPayloadError {
|
||||||
|
fn error_response(&self) -> HttpResponse {
|
||||||
|
match *self {
|
||||||
|
PathPayloadError::Deserialize(_) => {
|
||||||
|
HttpResponse::new(StatusCode::BAD_REQUEST)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A set of errors that can occur during parsing query strings
|
/// A set of errors that can occur during parsing query strings
|
||||||
#[derive(Debug, Display, From)]
|
#[derive(Debug, Display, From)]
|
||||||
pub enum QueryPayloadError {
|
pub enum QueryPayloadError {
|
||||||
|
@ -9,6 +9,6 @@ pub(crate) mod readlines;
|
|||||||
|
|
||||||
pub use self::form::{Form, FormConfig};
|
pub use self::form::{Form, FormConfig};
|
||||||
pub use self::json::{Json, JsonConfig};
|
pub use self::json::{Json, JsonConfig};
|
||||||
pub use self::path::Path;
|
pub use self::path::{Path, PathConfig};
|
||||||
pub use self::payload::{Payload, PayloadConfig};
|
pub use self::payload::{Payload, PayloadConfig};
|
||||||
pub use self::query::{Query, QueryConfig};
|
pub use self::query::{Query, QueryConfig};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! Path extractor
|
//! Path extractor
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
use std::{fmt, ops};
|
use std::{fmt, ops};
|
||||||
|
|
||||||
use actix_http::error::{Error, ErrorNotFound};
|
use actix_http::error::{Error, ErrorNotFound};
|
||||||
@ -7,6 +8,7 @@ use actix_router::PathDeserializer;
|
|||||||
use serde::de;
|
use serde::de;
|
||||||
|
|
||||||
use crate::dev::Payload;
|
use crate::dev::Payload;
|
||||||
|
use crate::error::PathPayloadError;
|
||||||
use crate::request::HttpRequest;
|
use crate::request::HttpRequest;
|
||||||
use crate::FromRequest;
|
use crate::FromRequest;
|
||||||
|
|
||||||
@ -156,15 +158,89 @@ impl<T> FromRequest for Path<T>
|
|||||||
where
|
where
|
||||||
T: de::DeserializeOwned,
|
T: de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
type Config = ();
|
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Future = Result<Self, Error>;
|
type Future = Result<Self, Error>;
|
||||||
|
type Config = PathConfig;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
|
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
|
||||||
|
let error_handler = req
|
||||||
|
.app_data::<Self::Config>()
|
||||||
|
.map(|c| c.ehandler.clone())
|
||||||
|
.unwrap_or(None);
|
||||||
|
|
||||||
de::Deserialize::deserialize(PathDeserializer::new(req.match_info()))
|
de::Deserialize::deserialize(PathDeserializer::new(req.match_info()))
|
||||||
.map(|inner| Path { inner })
|
.map(|inner| Path { inner })
|
||||||
.map_err(ErrorNotFound)
|
.map_err(move |e| {
|
||||||
|
log::debug!(
|
||||||
|
"Failed during Path extractor deserialization. \
|
||||||
|
Request path: {:?}",
|
||||||
|
req.path()
|
||||||
|
);
|
||||||
|
if let Some(error_handler) = error_handler {
|
||||||
|
let e = PathPayloadError::Deserialize(e);
|
||||||
|
(error_handler)(e, req)
|
||||||
|
} else {
|
||||||
|
ErrorNotFound(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Path extractor configuration
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
// #[macro_use]
|
||||||
|
// extern crate serde_derive;
|
||||||
|
// use actix_web::web::PathConfig;
|
||||||
|
// use actix_web::{error, web, App, FromRequest, HttpResponse};
|
||||||
|
|
||||||
|
// #[derive(Deserialize, Debug)]
|
||||||
|
// enum Folder {
|
||||||
|
// #[serde(rename = "inbox")]
|
||||||
|
// Inbox,
|
||||||
|
// #[serde(rename = "outbox")]
|
||||||
|
// Outbox,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /// deserialize `Info` from request's path
|
||||||
|
// fn index(folder: web::Path<Folder>) -> String {
|
||||||
|
// format!("Selected folder: {}!", folder)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn main() {
|
||||||
|
// let app = App::new().service(
|
||||||
|
// web::resource("messages/{folder}")
|
||||||
|
// .data(PathConfig::default().error_handler(|err, req| {
|
||||||
|
// error::InternalError::from_response(
|
||||||
|
// err,
|
||||||
|
// HttpResponse::Conflict().finish(),
|
||||||
|
// )
|
||||||
|
// .into()
|
||||||
|
// }))
|
||||||
|
// .route(web::post().to(index)),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct PathConfig {
|
||||||
|
ehandler: Option<Arc<Fn(PathPayloadError, &HttpRequest) -> Error + Send + Sync>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PathConfig {
|
||||||
|
/// Set custom error handler
|
||||||
|
pub fn error_handler<F>(mut self, f: F) -> Self
|
||||||
|
where
|
||||||
|
F: Fn(PathPayloadError, &HttpRequest) -> Error + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
self.ehandler = Some(Arc::new(f));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PathConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
PathConfig { ehandler: None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user