mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-28 01:32:57 +01:00
refactor extractor configuration #331
This commit is contained in:
parent
75eec8bd4f
commit
0093b7ea5a
32
MIGRATION.md
32
MIGRATION.md
@ -23,6 +23,38 @@
|
|||||||
* Renamed `client::ClientConnectorError::Connector` to
|
* Renamed `client::ClientConnectorError::Connector` to
|
||||||
`client::ClientConnectorError::Resolver`
|
`client::ClientConnectorError::Resolver`
|
||||||
|
|
||||||
|
* `Route::with()` does not return `ExtractorConfig`, to configure
|
||||||
|
extractor use `Route::with_config()`
|
||||||
|
|
||||||
|
instead of
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn main() {
|
||||||
|
let app = App::new().resource("/index.html", |r| {
|
||||||
|
r.method(http::Method::GET)
|
||||||
|
.with(index)
|
||||||
|
.limit(4096); // <- limit size of the payload
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
use
|
||||||
|
|
||||||
|
```rust
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let app = App::new().resource("/index.html", |r| {
|
||||||
|
r.method(http::Method::GET)
|
||||||
|
.with_config(index, |cfg| { // <- register handler
|
||||||
|
cfg.limit(4096); // <- limit size of the payload
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
* `Route::with_async()` does not return `ExtractorConfig`, to configure
|
||||||
|
extractor use `Route::with_async_config()`
|
||||||
|
|
||||||
|
|
||||||
## 0.6
|
## 0.6
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::{fmt, str};
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::{fmt, str};
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use encoding::all::UTF_8;
|
use encoding::all::UTF_8;
|
||||||
@ -328,7 +328,7 @@ impl<S> FormConfig<S> {
|
|||||||
self.limit = limit;
|
self.limit = limit;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set custom error handler
|
/// Set custom error handler
|
||||||
pub fn error_handler<F>(&mut self, f: F) -> &mut Self
|
pub fn error_handler<F>(&mut self, f: F) -> &mut Self
|
||||||
where
|
where
|
||||||
@ -408,8 +408,9 @@ impl<S: 'static> FromRequest<S> for Bytes {
|
|||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// let app = App::new().resource("/index.html", |r| {
|
/// let app = App::new().resource("/index.html", |r| {
|
||||||
/// r.method(http::Method::GET)
|
/// r.method(http::Method::GET)
|
||||||
/// .with(index) // <- register handler with extractor params
|
/// .with_config(index, |cfg| { // <- register handler with extractor params
|
||||||
/// .limit(4096); // <- limit size of the payload
|
/// cfg.limit(4096); // <- limit size of the payload
|
||||||
|
/// })
|
||||||
/// });
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -246,7 +246,6 @@ pub mod dev {
|
|||||||
pub use resource::ResourceHandler;
|
pub use resource::ResourceHandler;
|
||||||
pub use route::Route;
|
pub use route::Route;
|
||||||
pub use router::{Resource, ResourceType, Router};
|
pub use router::{Resource, ResourceType, Router};
|
||||||
pub use with::ExtractorConfig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod http {
|
pub mod http {
|
||||||
|
95
src/route.rs
95
src/route.rs
@ -17,7 +17,7 @@ use middleware::{
|
|||||||
Started as MiddlewareStarted,
|
Started as MiddlewareStarted,
|
||||||
};
|
};
|
||||||
use pred::Predicate;
|
use pred::Predicate;
|
||||||
use with::{ExtractorConfig, With, WithAsync};
|
use with::{With, WithAsync};
|
||||||
|
|
||||||
/// Resource route definition
|
/// Resource route definition
|
||||||
///
|
///
|
||||||
@ -164,15 +164,49 @@ impl<S: 'static> Route<S> {
|
|||||||
/// ); // <- use `with` extractor
|
/// ); // <- use `with` extractor
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn with<T, F, R>(&mut self, handler: F) -> ExtractorConfig<S, T>
|
pub fn with<T, F, R>(&mut self, handler: F)
|
||||||
where
|
where
|
||||||
F: Fn(T) -> R + 'static,
|
F: Fn(T) -> R + 'static,
|
||||||
R: Responder + 'static,
|
R: Responder + 'static,
|
||||||
T: FromRequest<S> + 'static,
|
T: FromRequest<S> + 'static,
|
||||||
{
|
{
|
||||||
let cfg = ExtractorConfig::<S, T>::default();
|
self.h(With::new(handler, <T::Config as Default>::default()));
|
||||||
self.h(With::new(handler, cfg.clone()));
|
}
|
||||||
cfg
|
|
||||||
|
/// Set handler function. Same as `.with()` but it allows to configure
|
||||||
|
/// extractor.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # extern crate bytes;
|
||||||
|
/// # extern crate actix_web;
|
||||||
|
/// # extern crate futures;
|
||||||
|
/// #[macro_use] extern crate serde_derive;
|
||||||
|
/// use actix_web::{http, App, Path, Result};
|
||||||
|
///
|
||||||
|
/// /// extract text data from request
|
||||||
|
/// fn index(body: String) -> Result<String> {
|
||||||
|
/// Ok(format!("Body {}!", body))
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// let app = App::new().resource("/index.html", |r| {
|
||||||
|
/// r.method(http::Method::GET)
|
||||||
|
/// .with_config(index, |cfg| { // <- register handler
|
||||||
|
/// cfg.limit(4096); // <- limit size of the payload
|
||||||
|
/// })
|
||||||
|
/// });
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn with_config<T, F, R, C>(&mut self, handler: F, cfg_f: C)
|
||||||
|
where
|
||||||
|
F: Fn(T) -> R + 'static,
|
||||||
|
R: Responder + 'static,
|
||||||
|
T: FromRequest<S> + 'static,
|
||||||
|
C: FnOnce(&mut T::Config),
|
||||||
|
{
|
||||||
|
let mut cfg = <T::Config as Default>::default();
|
||||||
|
cfg_f(&mut cfg);
|
||||||
|
self.h(With::new(handler, cfg));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set async handler function, use request extractor for parameters.
|
/// Set async handler function, use request extractor for parameters.
|
||||||
@ -204,7 +238,7 @@ impl<S: 'static> Route<S> {
|
|||||||
/// ); // <- use `with` extractor
|
/// ); // <- use `with` extractor
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn with_async<T, F, R, I, E>(&mut self, handler: F) -> ExtractorConfig<S, T>
|
pub fn with_async<T, F, R, I, E>(&mut self, handler: F)
|
||||||
where
|
where
|
||||||
F: Fn(T) -> R + 'static,
|
F: Fn(T) -> R + 'static,
|
||||||
R: Future<Item = I, Error = E> + 'static,
|
R: Future<Item = I, Error = E> + 'static,
|
||||||
@ -212,9 +246,52 @@ impl<S: 'static> Route<S> {
|
|||||||
E: Into<Error> + 'static,
|
E: Into<Error> + 'static,
|
||||||
T: FromRequest<S> + 'static,
|
T: FromRequest<S> + 'static,
|
||||||
{
|
{
|
||||||
let cfg = ExtractorConfig::<S, T>::default();
|
self.h(WithAsync::new(handler, <T::Config as Default>::default()));
|
||||||
self.h(WithAsync::new(handler, cfg.clone()));
|
}
|
||||||
cfg
|
|
||||||
|
/// Set async handler function, use request extractor for parameters.
|
||||||
|
/// This method allows to configure extractor.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # extern crate bytes;
|
||||||
|
/// # extern crate actix_web;
|
||||||
|
/// # extern crate futures;
|
||||||
|
/// #[macro_use] extern crate serde_derive;
|
||||||
|
/// use actix_web::{http, App, Error, Path};
|
||||||
|
/// use futures::Future;
|
||||||
|
///
|
||||||
|
/// #[derive(Deserialize)]
|
||||||
|
/// struct Info {
|
||||||
|
/// username: String,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// /// extract path info using serde
|
||||||
|
/// fn index(info: Form<Info>) -> Box<Future<Item = &'static str, Error = Error>> {
|
||||||
|
/// unimplemented!()
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// let app = App::new().resource(
|
||||||
|
/// "/{username}/index.html", // <- define path parameters
|
||||||
|
/// |r| r.method(http::Method::GET)
|
||||||
|
/// .with_async_config(index, |cfg| {
|
||||||
|
/// cfg.limit(4096);
|
||||||
|
/// }),
|
||||||
|
/// ); // <- use `with` extractor
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn with_async_config<T, F, R, I, E, C>(&mut self, handler: F, cfg: C)
|
||||||
|
where
|
||||||
|
F: Fn(T) -> R + 'static,
|
||||||
|
R: Future<Item = I, Error = E> + 'static,
|
||||||
|
I: Responder + 'static,
|
||||||
|
E: Into<Error> + 'static,
|
||||||
|
T: FromRequest<S> + 'static,
|
||||||
|
C: FnOnce(&mut T::Config),
|
||||||
|
{
|
||||||
|
let mut extractor_cfg = <T::Config as Default>::default();
|
||||||
|
cfg(&mut extractor_cfg);
|
||||||
|
self.h(WithAsync::new(handler, extractor_cfg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
119
src/with.rs
119
src/with.rs
@ -1,7 +1,6 @@
|
|||||||
use futures::{Async, Future, Poll};
|
use futures::{Async, Future, Poll};
|
||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
@ -9,110 +8,14 @@ use handler::{AsyncResult, AsyncResultItem, FromRequest, Handler, Responder};
|
|||||||
use httprequest::HttpRequest;
|
use httprequest::HttpRequest;
|
||||||
use httpresponse::HttpResponse;
|
use httpresponse::HttpResponse;
|
||||||
|
|
||||||
/// Extractor configuration
|
pub(crate) struct With<T, S, F, R>
|
||||||
///
|
|
||||||
/// `Route::with()` and `Route::with_async()` returns instance
|
|
||||||
/// of the `ExtractorConfig` type. It could be used for extractor configuration.
|
|
||||||
///
|
|
||||||
/// In this example `Form<FormData>` configured.
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # extern crate actix_web;
|
|
||||||
/// #[macro_use] extern crate serde_derive;
|
|
||||||
/// use actix_web::{http, App, Form, Result};
|
|
||||||
///
|
|
||||||
/// #[derive(Deserialize)]
|
|
||||||
/// struct FormData {
|
|
||||||
/// username: String,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn index(form: Form<FormData>) -> Result<String> {
|
|
||||||
/// Ok(format!("Welcome {}!", form.username))
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// let app = App::new().resource(
|
|
||||||
/// "/index.html",
|
|
||||||
/// |r| {
|
|
||||||
/// r.method(http::Method::GET).with(index).limit(4096);
|
|
||||||
/// }, // <- change form extractor configuration
|
|
||||||
/// );
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Same could be donce with multiple extractors
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # extern crate actix_web;
|
|
||||||
/// #[macro_use] extern crate serde_derive;
|
|
||||||
/// use actix_web::{http, App, Form, Path, Result};
|
|
||||||
///
|
|
||||||
/// #[derive(Deserialize)]
|
|
||||||
/// struct FormData {
|
|
||||||
/// username: String,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn index(data: (Path<(String,)>, Form<FormData>)) -> Result<String> {
|
|
||||||
/// Ok(format!("Welcome {}!", data.1.username))
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// let app = App::new().resource(
|
|
||||||
/// "/index.html",
|
|
||||||
/// |r| {
|
|
||||||
/// r.method(http::Method::GET).with(index).1.limit(4096);
|
|
||||||
/// }, // <- change form extractor configuration
|
|
||||||
/// );
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub struct ExtractorConfig<S: 'static, T: FromRequest<S>> {
|
|
||||||
cfg: Rc<UnsafeCell<T::Config>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: 'static, T: FromRequest<S>> Default for ExtractorConfig<S, T> {
|
|
||||||
fn default() -> Self {
|
|
||||||
ExtractorConfig {
|
|
||||||
cfg: Rc::new(UnsafeCell::new(T::Config::default())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: 'static, T: FromRequest<S>> ExtractorConfig<S, T> {
|
|
||||||
pub(crate) fn clone(&self) -> Self {
|
|
||||||
ExtractorConfig {
|
|
||||||
cfg: Rc::clone(&self.cfg),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: 'static, T: FromRequest<S>> AsRef<T::Config> for ExtractorConfig<S, T> {
|
|
||||||
fn as_ref(&self) -> &T::Config {
|
|
||||||
unsafe { &*self.cfg.get() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: 'static, T: FromRequest<S>> Deref for ExtractorConfig<S, T> {
|
|
||||||
type Target = T::Config;
|
|
||||||
|
|
||||||
fn deref(&self) -> &T::Config {
|
|
||||||
unsafe { &*self.cfg.get() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: 'static, T: FromRequest<S>> DerefMut for ExtractorConfig<S, T> {
|
|
||||||
fn deref_mut(&mut self) -> &mut T::Config {
|
|
||||||
unsafe { &mut *self.cfg.get() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct With<T, S, F, R>
|
|
||||||
where
|
where
|
||||||
F: Fn(T) -> R,
|
F: Fn(T) -> R,
|
||||||
T: FromRequest<S>,
|
T: FromRequest<S>,
|
||||||
S: 'static,
|
S: 'static,
|
||||||
{
|
{
|
||||||
hnd: Rc<WithHnd<T, S, F, R>>,
|
hnd: Rc<WithHnd<T, S, F, R>>,
|
||||||
cfg: ExtractorConfig<S, T>,
|
cfg: Rc<T::Config>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WithHnd<T, S, F, R>
|
pub struct WithHnd<T, S, F, R>
|
||||||
@ -132,9 +35,9 @@ where
|
|||||||
T: FromRequest<S>,
|
T: FromRequest<S>,
|
||||||
S: 'static,
|
S: 'static,
|
||||||
{
|
{
|
||||||
pub fn new(f: F, cfg: ExtractorConfig<S, T>) -> Self {
|
pub fn new(f: F, cfg: T::Config) -> Self {
|
||||||
With {
|
With {
|
||||||
cfg,
|
cfg: Rc::new(cfg),
|
||||||
hnd: Rc::new(WithHnd {
|
hnd: Rc::new(WithHnd {
|
||||||
hnd: Rc::new(UnsafeCell::new(f)),
|
hnd: Rc::new(UnsafeCell::new(f)),
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
@ -180,7 +83,7 @@ where
|
|||||||
{
|
{
|
||||||
started: bool,
|
started: bool,
|
||||||
hnd: Rc<WithHnd<T, S, F, R>>,
|
hnd: Rc<WithHnd<T, S, F, R>>,
|
||||||
cfg: ExtractorConfig<S, T>,
|
cfg: Rc<T::Config>,
|
||||||
req: HttpRequest<S>,
|
req: HttpRequest<S>,
|
||||||
fut1: Option<Box<Future<Item = T, Error = Error>>>,
|
fut1: Option<Box<Future<Item = T, Error = Error>>>,
|
||||||
fut2: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
|
fut2: Option<Box<Future<Item = HttpResponse, Error = Error>>>,
|
||||||
@ -244,7 +147,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WithAsync<T, S, F, R, I, E>
|
pub(crate) struct WithAsync<T, S, F, R, I, E>
|
||||||
where
|
where
|
||||||
F: Fn(T) -> R,
|
F: Fn(T) -> R,
|
||||||
R: Future<Item = I, Error = E>,
|
R: Future<Item = I, Error = E>,
|
||||||
@ -254,7 +157,7 @@ where
|
|||||||
S: 'static,
|
S: 'static,
|
||||||
{
|
{
|
||||||
hnd: Rc<WithHnd<T, S, F, R>>,
|
hnd: Rc<WithHnd<T, S, F, R>>,
|
||||||
cfg: ExtractorConfig<S, T>,
|
cfg: Rc<T::Config>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, S, F, R, I, E> WithAsync<T, S, F, R, I, E>
|
impl<T, S, F, R, I, E> WithAsync<T, S, F, R, I, E>
|
||||||
@ -266,9 +169,9 @@ where
|
|||||||
T: FromRequest<S>,
|
T: FromRequest<S>,
|
||||||
S: 'static,
|
S: 'static,
|
||||||
{
|
{
|
||||||
pub fn new(f: F, cfg: ExtractorConfig<S, T>) -> Self {
|
pub fn new(f: F, cfg: T::Config) -> Self {
|
||||||
WithAsync {
|
WithAsync {
|
||||||
cfg,
|
cfg: Rc::new(cfg),
|
||||||
hnd: Rc::new(WithHnd {
|
hnd: Rc::new(WithHnd {
|
||||||
hnd: Rc::new(UnsafeCell::new(f)),
|
hnd: Rc::new(UnsafeCell::new(f)),
|
||||||
_s: PhantomData,
|
_s: PhantomData,
|
||||||
@ -294,7 +197,7 @@ where
|
|||||||
req,
|
req,
|
||||||
started: false,
|
started: false,
|
||||||
hnd: Rc::clone(&self.hnd),
|
hnd: Rc::clone(&self.hnd),
|
||||||
cfg: self.cfg.clone(),
|
cfg: Rc::clone(&self.cfg),
|
||||||
fut1: None,
|
fut1: None,
|
||||||
fut2: None,
|
fut2: None,
|
||||||
fut3: None,
|
fut3: None,
|
||||||
@ -319,7 +222,7 @@ where
|
|||||||
{
|
{
|
||||||
started: bool,
|
started: bool,
|
||||||
hnd: Rc<WithHnd<T, S, F, R>>,
|
hnd: Rc<WithHnd<T, S, F, R>>,
|
||||||
cfg: ExtractorConfig<S, T>,
|
cfg: Rc<T::Config>,
|
||||||
req: HttpRequest<S>,
|
req: HttpRequest<S>,
|
||||||
fut1: Option<Box<Future<Item = T, Error = Error>>>,
|
fut1: Option<Box<Future<Item = T, Error = Error>>>,
|
||||||
fut2: Option<R>,
|
fut2: Option<R>,
|
||||||
|
Loading…
Reference in New Issue
Block a user