mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-27 17:22: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
|
||||
`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
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::{fmt, str};
|
||||
use std::rc::Rc;
|
||||
use std::{fmt, str};
|
||||
|
||||
use bytes::Bytes;
|
||||
use encoding::all::UTF_8;
|
||||
@ -328,7 +328,7 @@ impl<S> FormConfig<S> {
|
||||
self.limit = limit;
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
/// Set custom error handler
|
||||
pub fn error_handler<F>(&mut self, f: F) -> &mut Self
|
||||
where
|
||||
@ -408,8 +408,9 @@ impl<S: 'static> FromRequest<S> for Bytes {
|
||||
/// fn main() {
|
||||
/// let app = App::new().resource("/index.html", |r| {
|
||||
/// r.method(http::Method::GET)
|
||||
/// .with(index) // <- register handler with extractor params
|
||||
/// .limit(4096); // <- limit size of the payload
|
||||
/// .with_config(index, |cfg| { // <- register handler with extractor params
|
||||
/// cfg.limit(4096); // <- limit size of the payload
|
||||
/// })
|
||||
/// });
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -246,7 +246,6 @@ pub mod dev {
|
||||
pub use resource::ResourceHandler;
|
||||
pub use route::Route;
|
||||
pub use router::{Resource, ResourceType, Router};
|
||||
pub use with::ExtractorConfig;
|
||||
}
|
||||
|
||||
pub mod http {
|
||||
|
95
src/route.rs
95
src/route.rs
@ -17,7 +17,7 @@ use middleware::{
|
||||
Started as MiddlewareStarted,
|
||||
};
|
||||
use pred::Predicate;
|
||||
use with::{ExtractorConfig, With, WithAsync};
|
||||
use with::{With, WithAsync};
|
||||
|
||||
/// Resource route definition
|
||||
///
|
||||
@ -164,15 +164,49 @@ impl<S: 'static> Route<S> {
|
||||
/// ); // <- 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
|
||||
F: Fn(T) -> R + 'static,
|
||||
R: Responder + 'static,
|
||||
T: FromRequest<S> + 'static,
|
||||
{
|
||||
let cfg = ExtractorConfig::<S, T>::default();
|
||||
self.h(With::new(handler, cfg.clone()));
|
||||
cfg
|
||||
self.h(With::new(handler, <T::Config as Default>::default()));
|
||||
}
|
||||
|
||||
/// 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.
|
||||
@ -204,7 +238,7 @@ impl<S: 'static> Route<S> {
|
||||
/// ); // <- 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
|
||||
F: Fn(T) -> R + 'static,
|
||||
R: Future<Item = I, Error = E> + 'static,
|
||||
@ -212,9 +246,52 @@ impl<S: 'static> Route<S> {
|
||||
E: Into<Error> + 'static,
|
||||
T: FromRequest<S> + 'static,
|
||||
{
|
||||
let cfg = ExtractorConfig::<S, T>::default();
|
||||
self.h(WithAsync::new(handler, cfg.clone()));
|
||||
cfg
|
||||
self.h(WithAsync::new(handler, <T::Config as Default>::default()));
|
||||
}
|
||||
|
||||
/// 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 std::cell::UnsafeCell;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::rc::Rc;
|
||||
|
||||
use error::Error;
|
||||
@ -9,110 +8,14 @@ use handler::{AsyncResult, AsyncResultItem, FromRequest, Handler, Responder};
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
|
||||
/// Extractor configuration
|
||||
///
|
||||
/// `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>
|
||||
pub(crate) struct With<T, S, F, R>
|
||||
where
|
||||
F: Fn(T) -> R,
|
||||
T: FromRequest<S>,
|
||||
S: 'static,
|
||||
{
|
||||
hnd: Rc<WithHnd<T, S, F, R>>,
|
||||
cfg: ExtractorConfig<S, T>,
|
||||
cfg: Rc<T::Config>,
|
||||
}
|
||||
|
||||
pub struct WithHnd<T, S, F, R>
|
||||
@ -132,9 +35,9 @@ where
|
||||
T: FromRequest<S>,
|
||||
S: 'static,
|
||||
{
|
||||
pub fn new(f: F, cfg: ExtractorConfig<S, T>) -> Self {
|
||||
pub fn new(f: F, cfg: T::Config) -> Self {
|
||||
With {
|
||||
cfg,
|
||||
cfg: Rc::new(cfg),
|
||||
hnd: Rc::new(WithHnd {
|
||||
hnd: Rc::new(UnsafeCell::new(f)),
|
||||
_t: PhantomData,
|
||||
@ -180,7 +83,7 @@ where
|
||||
{
|
||||
started: bool,
|
||||
hnd: Rc<WithHnd<T, S, F, R>>,
|
||||
cfg: ExtractorConfig<S, T>,
|
||||
cfg: Rc<T::Config>,
|
||||
req: HttpRequest<S>,
|
||||
fut1: Option<Box<Future<Item = T, 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
|
||||
F: Fn(T) -> R,
|
||||
R: Future<Item = I, Error = E>,
|
||||
@ -254,7 +157,7 @@ where
|
||||
S: 'static,
|
||||
{
|
||||
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>
|
||||
@ -266,9 +169,9 @@ where
|
||||
T: FromRequest<S>,
|
||||
S: 'static,
|
||||
{
|
||||
pub fn new(f: F, cfg: ExtractorConfig<S, T>) -> Self {
|
||||
pub fn new(f: F, cfg: T::Config) -> Self {
|
||||
WithAsync {
|
||||
cfg,
|
||||
cfg: Rc::new(cfg),
|
||||
hnd: Rc::new(WithHnd {
|
||||
hnd: Rc::new(UnsafeCell::new(f)),
|
||||
_s: PhantomData,
|
||||
@ -294,7 +197,7 @@ where
|
||||
req,
|
||||
started: false,
|
||||
hnd: Rc::clone(&self.hnd),
|
||||
cfg: self.cfg.clone(),
|
||||
cfg: Rc::clone(&self.cfg),
|
||||
fut1: None,
|
||||
fut2: None,
|
||||
fut3: None,
|
||||
@ -319,7 +222,7 @@ where
|
||||
{
|
||||
started: bool,
|
||||
hnd: Rc<WithHnd<T, S, F, R>>,
|
||||
cfg: ExtractorConfig<S, T>,
|
||||
cfg: Rc<T::Config>,
|
||||
req: HttpRequest<S>,
|
||||
fut1: Option<Box<Future<Item = T, Error = Error>>>,
|
||||
fut2: Option<R>,
|
||||
|
Loading…
Reference in New Issue
Block a user