Rename data (#98)

* Rename data to state
This commit is contained in:
Nikolay Kim 2022-01-23 21:31:22 +06:00 committed by GitHub
parent 5d9a653f70
commit 68e9603808
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 303 additions and 289 deletions

View file

@ -4,6 +4,8 @@
* web: Refactor ws support
* web: Rename data to state
* web: Add types::Payload::recv() and types::Payload::poll_recv() methods
## [0.5.10] - 2022-01-17

View file

@ -16,13 +16,13 @@ use super::resource::Resource;
use super::response::WebResponse;
use super::route::Route;
use super::service::{AppServiceFactory, ServiceFactoryWrapper, WebServiceFactory};
use super::types::data::{Data, DataFactory};
use super::types::state::{State, StateFactory};
use super::{DefaultError, ErrorRenderer};
type HttpNewService<Err: ErrorRenderer> =
BoxServiceFactory<(), WebRequest<Err>, WebResponse, Err::Container, ()>;
type FnDataFactory =
Box<dyn Fn() -> Pin<Box<dyn Future<Output = Result<Box<dyn DataFactory>, ()>>>>>;
type FnStateFactory =
Box<dyn Fn() -> Pin<Box<dyn Future<Output = Result<Box<dyn StateFactory>, ()>>>>>;
/// Application builder - structure that follows the builder pattern
/// for building application instances.
@ -31,8 +31,8 @@ pub struct App<M, F, Err: ErrorRenderer = DefaultError> {
filter: PipelineFactory<F, WebRequest<Err>>,
services: Vec<Box<dyn AppServiceFactory<Err>>>,
default: Option<Rc<HttpNewService<Err>>>,
data: Vec<Box<dyn DataFactory>>,
data_factories: Vec<FnDataFactory>,
state: Vec<Box<dyn StateFactory>>,
state_factories: Vec<FnStateFactory>,
external: Vec<ResourceDef>,
extensions: Extensions,
error_renderer: Err,
@ -45,8 +45,8 @@ impl App<Identity, Filter<DefaultError>, DefaultError> {
App {
middleware: Identity,
filter: pipeline_factory(Filter::new()),
data: Vec::new(),
data_factories: Vec::new(),
state: Vec::new(),
state_factories: Vec::new(),
services: Vec::new(),
default: None,
external: Vec::new(),
@ -63,8 +63,8 @@ impl<Err: ErrorRenderer> App<Identity, Filter<Err>, Err> {
App {
middleware: Identity,
filter: pipeline_factory(Filter::new()),
data: Vec::new(),
data_factories: Vec::new(),
state: Vec::new(),
state_factories: Vec::new(),
services: Vec::new(),
default: None,
external: Vec::new(),
@ -86,62 +86,68 @@ where
T::Future: 'static,
Err: ErrorRenderer,
{
/// Set application data. Application data could be accessed
/// by using `Data<T>` extractor where `T` is data type.
/// Set application state. Application state could be accessed
/// by using `State<T>` extractor where `T` is state type.
///
/// **Note**: http server accepts an application factory rather than
/// an application instance. Http server constructs an application
/// instance for each thread, thus application data must be constructed
/// multiple times. If you want to share data between different
/// threads, a shared object should be used, e.g. `Arc`. Internally `Data` type
/// uses `Arc` so data could be created outside of app factory and clones could
/// be stored via `App::app_data()` method.
/// instance for each thread, thus application state must be constructed
/// multiple times. If you want to share state between different
/// threads, a shared object should be used, e.g. `Arc`. Internally `State` type
/// uses `Arc` so statw could be created outside of app factory and clones could
/// be stored via `App::app_state()` method.
///
/// ```rust
/// use std::cell::Cell;
/// use ntex::web::{self, App, HttpResponse};
///
/// struct MyData {
/// struct MyState {
/// counter: Cell<usize>,
/// }
///
/// async fn index(data: web::types::Data<MyData>) -> HttpResponse {
/// data.counter.set(data.counter.get() + 1);
/// async fn index(st: web::types::State<MyState>) -> HttpResponse {
/// st.counter.set(st.counter.get() + 1);
/// HttpResponse::Ok().into()
/// }
///
/// let app = App::new()
/// .data(MyData{ counter: Cell::new(0) })
/// .state(MyState{ counter: Cell::new(0) })
/// .service(
/// web::resource("/index.html").route(web::get().to(index))
/// );
/// ```
pub fn data<U: 'static>(mut self, data: U) -> Self {
self.data.push(Box::new(Data::new(data)));
pub fn state<U: 'static>(mut self, state: U) -> Self {
self.state.push(Box::new(State::new(state)));
self
}
/// Set application data factory. This function is
/// similar to `.data()` but it accepts data factory. Data object get
#[deprecated]
#[doc(hidden)]
pub fn data<U: 'static>(self, data: U) -> Self {
self.state(data)
}
/// Set application state factory. This function is
/// similar to `.state()` but it accepts state factory. State object get
/// constructed asynchronously during application initialization.
pub fn data_factory<F, Out, D, E>(mut self, data: F) -> Self
pub fn state_factory<F, Out, D, E>(mut self, state: F) -> Self
where
F: Fn() -> Out + 'static,
Out: Future<Output = Result<D, E>> + 'static,
D: 'static,
E: std::fmt::Debug,
E: fmt::Debug,
{
self.data_factories.push(Box::new(move || {
let fut = data();
self.state_factories.push(Box::new(move || {
let fut = state();
Box::pin(async move {
match fut.await {
Err(e) => {
log::error!("Cannot construct data instance: {:?}", e);
log::error!("Cannot construct state instance: {:?}", e);
Err(())
}
Ok(data) => {
let data: Box<dyn DataFactory> = Box::new(Data::new(data));
Ok(data)
Ok(st) => {
let st: Box<dyn StateFactory> = Box::new(State::new(st));
Ok(st)
}
}
})
@ -149,14 +155,14 @@ where
self
}
/// Set application level arbitrary data item.
/// Set application level arbitrary state item.
///
/// Application data stored with `App::app_data()` method is available
/// via `HttpRequest::app_data()` method at runtime.
/// Application state stored with `App::app_state()` method is available
/// via `HttpRequest::app_state()` method at runtime.
///
/// This method could be used for storing `Data<T>` as well, in that case
/// data could be accessed by using `Data<T>` extractor.
pub fn app_data<U: 'static>(mut self, ext: U) -> Self {
/// This method could be used for storing `State<T>` as well, in that case
/// state could be accessed by using `State<T>` extractor.
pub fn app_state<U: 'static>(mut self, ext: U) -> Self {
self.extensions.insert(ext);
self
}
@ -192,7 +198,7 @@ where
{
let mut cfg = ServiceConfig::new();
f(&mut cfg);
self.data.extend(cfg.data);
self.state.extend(cfg.state);
self.services.extend(cfg.services);
self.external.extend(cfg.external);
self
@ -375,8 +381,8 @@ where
App {
filter: self.filter.and_then(filter.into_factory()),
middleware: self.middleware,
data: self.data,
data_factories: self.data_factories,
state: self.state,
state_factories: self.state_factories,
services: self.services,
default: self.default,
external: self.external,
@ -416,8 +422,8 @@ where
App {
middleware: Stack::new(self.middleware, mw),
filter: self.filter,
data: self.data,
data_factories: self.data_factories,
state: self.state,
state_factories: self.state_factories,
services: self.services,
default: self.default,
external: self.external,
@ -508,8 +514,8 @@ where
let app = AppFactory {
filter: self.filter,
middleware: Rc::new(self.middleware),
data: Rc::new(self.data),
data_factories: Rc::new(self.data_factories),
state: Rc::new(self.state),
state_factories: Rc::new(self.state_factories),
services: Rc::new(RefCell::new(self.services)),
external: RefCell::new(self.external),
default: self.default,
@ -538,8 +544,8 @@ where
AppFactory {
filter: self.filter,
middleware: Rc::new(self.middleware),
data: Rc::new(self.data),
data_factories: Rc::new(self.data_factories),
state: Rc::new(self.state),
state_factories: Rc::new(self.state_factories),
services: Rc::new(RefCell::new(self.services)),
external: RefCell::new(self.external),
default: self.default,
@ -566,8 +572,8 @@ where
AppFactory {
filter: self.filter,
middleware: Rc::new(self.middleware),
data: Rc::new(self.data),
data_factories: Rc::new(self.data_factories),
state: Rc::new(self.state),
state_factories: Rc::new(self.state_factories),
services: Rc::new(RefCell::new(self.services)),
external: RefCell::new(self.external),
default: self.default,
@ -696,13 +702,13 @@ mod tests {
}
#[crate::rt_test]
async fn test_data_factory() {
async fn test_state_factory() {
let srv = init_service(
App::new()
.data_factory(|| async { Ok::<_, ()>(10usize) })
.state_factory(|| async { Ok::<_, ()>(10usize) })
.service(
web::resource("/")
.to(|_: web::types::Data<usize>| async { HttpResponse::Ok() }),
.to(|_: web::types::State<usize>| async { HttpResponse::Ok() }),
),
)
.await;
@ -712,10 +718,10 @@ mod tests {
let srv = init_service(
App::new()
.data_factory(|| async { Ok::<_, ()>(10u32) })
.state_factory(|| async { Ok::<_, ()>(10u32) })
.service(
web::resource("/")
.to(|_: web::types::Data<usize>| async { HttpResponse::Ok() }),
.to(|_: web::types::State<usize>| async { HttpResponse::Ok() }),
),
)
.await;
@ -726,9 +732,9 @@ mod tests {
#[crate::rt_test]
async fn test_extension() {
let srv = init_service(App::new().app_data(10usize).service(
let srv = init_service(App::new().app_state(10usize).service(
web::resource("/").to(|req: HttpRequest| async move {
assert_eq!(*req.app_data::<usize>().unwrap(), 10);
assert_eq!(*req.app_state::<usize>().unwrap(), 10);
HttpResponse::Ok()
}),
))

View file

@ -15,7 +15,7 @@ use super::request::WebRequest;
use super::response::WebResponse;
use super::rmap::ResourceMap;
use super::service::{AppServiceFactory, WebServiceConfig};
use super::types::data::DataFactory;
use super::types::state::StateFactory;
type Guards = Vec<Box<dyn Guard>>;
type HttpService<Err: ErrorRenderer> =
@ -24,11 +24,11 @@ type HttpNewService<Err: ErrorRenderer> =
BoxServiceFactory<(), WebRequest<Err>, WebResponse, Err::Container, ()>;
type BoxResponse<Err: ErrorRenderer> =
Pin<Box<dyn Future<Output = Result<WebResponse, Err::Container>>>>;
type FnDataFactory =
Box<dyn Fn() -> Pin<Box<dyn Future<Output = Result<Box<dyn DataFactory>, ()>>>>>;
type FnStateFactory =
Box<dyn Fn() -> Pin<Box<dyn Future<Output = Result<Box<dyn StateFactory>, ()>>>>>;
/// Service factory to convert `Request` to a `WebRequest<S>`.
/// It also executes data factories.
/// It also executes state factories.
pub struct AppFactory<T, F, Err: ErrorRenderer>
where
F: ServiceFactory<
@ -43,8 +43,8 @@ where
pub(super) middleware: Rc<T>,
pub(super) filter: PipelineFactory<F, WebRequest<Err>>,
pub(super) extensions: RefCell<Option<Extensions>>,
pub(super) data: Rc<Vec<Box<dyn DataFactory>>>,
pub(super) data_factories: Rc<Vec<FnDataFactory>>,
pub(super) state: Rc<Vec<Box<dyn StateFactory>>>,
pub(super) state_factories: Rc<Vec<FnStateFactory>>,
pub(super) services: Rc<RefCell<Vec<Box<dyn AppServiceFactory<Err>>>>>,
pub(super) default: Option<Rc<HttpNewService<Err>>>,
pub(super) external: RefCell<Vec<ResourceDef>>,
@ -105,7 +105,7 @@ where
});
// App config
let mut config = WebServiceConfig::new(config, default.clone(), self.data.clone());
let mut config = WebServiceConfig::new(config, default.clone(), self.state.clone());
// register services
std::mem::take(&mut *self.services.borrow_mut())
@ -139,8 +139,8 @@ where
rmap.finish(rmap.clone());
let filter_fut = self.filter.new_service(());
let data = self.data.clone();
let data_factories = self.data_factories.clone();
let state = self.state.clone();
let state_factories = self.state_factories.clone();
let mut extensions = self
.extensions
.borrow_mut()
@ -166,13 +166,13 @@ where
routing: Rc::new(routing),
};
// create app data container
for f in data.iter() {
// create app state container
for f in state.iter() {
f.create(&mut extensions);
}
// async data factories
for fut in data_factories.iter() {
// async state factories
for fut in state_factories.iter() {
if let Ok(f) = fut().await {
f.create(&mut extensions);
}
@ -182,7 +182,7 @@ where
rmap,
config,
service: middleware.new_transform(service),
data: Rc::new(extensions),
state: Rc::new(extensions),
pool: HttpRequestPool::create(),
_t: PhantomData,
})
@ -199,7 +199,7 @@ where
service: T,
rmap: Rc<ResourceMap>,
config: AppConfig,
data: Rc<Extensions>,
state: Rc<Extensions>,
pool: &'static HttpRequestPool,
_t: PhantomData<Err>,
}
@ -231,7 +231,7 @@ where
inner.path.set(head.uri.clone());
inner.head = head;
inner.payload = payload;
inner.app_data = self.data.clone();
inner.app_state = self.state.clone();
req
} else {
HttpRequest::new(
@ -240,7 +240,7 @@ where
payload,
self.rmap.clone(),
self.config.clone(),
self.data.clone(),
self.state.clone(),
self.pool,
)
};
@ -388,7 +388,7 @@ mod tests {
{
let app = init_service(
App::new()
.data(DropData(data.clone()))
.state(DropData(data.clone()))
.service(web::resource("/test").to(|| async { HttpResponse::Ok() })),
)
.await;

View file

@ -5,7 +5,7 @@ use crate::router::ResourceDef;
use super::resource::Resource;
use super::route::Route;
use super::service::{AppServiceFactory, ServiceFactoryWrapper, WebServiceFactory};
use super::types::data::{Data, DataFactory};
use super::types::state::{State, StateFactory};
use super::{DefaultError, ErrorRenderer};
/// Application configuration
@ -61,7 +61,7 @@ impl Default for AppConfig {
/// modularization of big application configuration.
pub struct ServiceConfig<Err = DefaultError> {
pub(super) services: Vec<Box<dyn AppServiceFactory<Err>>>,
pub(super) data: Vec<Box<dyn DataFactory>>,
pub(super) state: Vec<Box<dyn StateFactory>>,
pub(super) external: Vec<ResourceDef>,
}
@ -69,17 +69,17 @@ impl<Err: ErrorRenderer> ServiceConfig<Err> {
pub(crate) fn new() -> Self {
Self {
services: Vec::new(),
data: Vec::new(),
state: Vec::new(),
external: Vec::new(),
}
}
/// Set application data. Application data could be accessed
/// by using `Data<T>` extractor where `T` is data type.
/// Set application state. Application state could be accessed
/// by using `State<T>` extractor where `T` is state type.
///
/// This is same as `App::data()` method.
pub fn data<S: 'static>(&mut self, data: S) -> &mut Self {
self.data.push(Box::new(Data::new(data)));
/// This is same as `App::state()` method.
pub fn state<S: 'static>(&mut self, st: S) -> &mut Self {
self.state.push(Box::new(State::new(st)));
self
}
@ -134,15 +134,15 @@ mod tests {
use crate::{service::Service, util::Bytes};
#[crate::rt_test]
async fn test_configure_data() {
async fn test_configure_state() {
let cfg = |cfg: &mut ServiceConfig<_>| {
cfg.data(10usize);
cfg.state(10usize);
};
let srv = init_service(
App::new().configure(cfg).service(
web::resource("/")
.to(|_: web::types::Data<usize>| async { HttpResponse::Ok() }),
.to(|_: web::types::State<usize>| async { HttpResponse::Ok() }),
),
)
.await;

View file

@ -268,7 +268,7 @@ mod tests {
header::CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.data(FormConfig::default().limit(4096))
.state(FormConfig::default().limit(4096))
.to_http_parts();
let r = from_request::<Option<Form<Info>>>(&req, &mut pl)

View file

@ -21,7 +21,7 @@ pub(crate) struct HttpRequestInner {
pub(crate) head: Message<RequestHead>,
pub(crate) path: Path<Uri>,
pub(crate) payload: Payload,
pub(crate) app_data: Rc<Extensions>,
pub(crate) app_state: Rc<Extensions>,
rmap: Rc<ResourceMap>,
config: AppConfig,
pool: &'static HttpRequestPool,
@ -35,14 +35,14 @@ impl HttpRequest {
payload: Payload,
rmap: Rc<ResourceMap>,
config: AppConfig,
app_data: Rc<Extensions>,
app_state: Rc<Extensions>,
pool: &'static HttpRequestPool,
) -> HttpRequest {
HttpRequest(Rc::new(HttpRequestInner {
head,
path,
payload,
app_data,
app_state,
rmap,
config,
pool,
@ -216,16 +216,16 @@ impl HttpRequest {
&self.0.config
}
/// Get an application data object stored with `App::data` or `App::app_data`
/// Get an application state object stored with `App::state()` or `App::app_state()`
/// methods during application configuration.
///
/// If `App::data` was used to store object, use `Data<T>`:
/// If `App::state()` was used to store object, use `State<T>`:
///
/// ```rust,ignore
/// let opt_t = req.app_data::<Data<T>>();
/// let opt_t = req.app_data::<State<T>>();
/// ```
pub fn app_data<T: 'static>(&self) -> Option<&T> {
self.0.app_data.get::<T>()
pub fn app_state<T: 'static>(&self) -> Option<&T> {
self.0.app_state.get::<T>()
}
}
@ -466,10 +466,10 @@ mod tests {
}
#[crate::rt_test]
async fn test_data() {
let srv = init_service(App::new().app_data(10usize).service(
async fn test_state() {
let srv = init_service(App::new().app_state(10usize).service(
web::resource("/").to(|req: HttpRequest| async move {
if req.app_data::<usize>().is_some() {
if req.app_state::<usize>().is_some() {
HttpResponse::Ok()
} else {
HttpResponse::BadRequest()
@ -482,9 +482,9 @@ mod tests {
let resp = call_service(&srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
let srv = init_service(App::new().app_data(10u32).service(web::resource("/").to(
let srv = init_service(App::new().app_state(10u32).service(web::resource("/").to(
|req: HttpRequest| async move {
if req.app_data::<usize>().is_some() {
if req.app_state::<usize>().is_some() {
HttpResponse::Ok()
} else {
HttpResponse::BadRequest()
@ -515,7 +515,7 @@ mod tests {
let tracker = Rc::new(RefCell::new(Tracker { dropped: false }));
{
let tracker2 = Rc::clone(&tracker);
let srv = init_service(App::new().data(10u32).service(web::resource("/").to(
let srv = init_service(App::new().state(10u32).service(web::resource("/").to(
move |req: HttpRequest| {
req.extensions_mut().insert(Foo {
tracker: Rc::clone(&tracker2),

View file

@ -202,12 +202,12 @@ impl<Err> WebRequest<Err> {
}
#[inline]
/// Get an application data stored with `App::app_data()` method during
/// Get an application state stored with `App::app_state()` method during
/// application configuration.
///
/// To get data stored with `App::data()` use `web::types::Data<T>` as type.
pub fn app_data<T: 'static>(&self) -> Option<&T> {
(self.req).0.app_data.get::<T>()
/// To get state stored with `App::state()` use `web::types::State<T>` as type.
pub fn app_state<T: 'static>(&self) -> Option<&T> {
(self.req).0.app_state.get::<T>()
}
#[inline]
@ -223,9 +223,9 @@ impl<Err> WebRequest<Err> {
}
#[doc(hidden)]
/// Set new app data container
pub fn set_data_container(&mut self, extensions: Rc<Extensions>) {
Rc::get_mut(&mut (self.req).0).unwrap().app_data = extensions;
/// Set new app state container
pub fn set_state_container(&mut self, extensions: Rc<Extensions>) {
Rc::get_mut(&mut (self.req).0).unwrap().app_state = extensions;
}
/// Request extensions

View file

@ -12,13 +12,12 @@ use crate::util::{Either, Extensions, Ready};
use super::dev::{insert_slesh, WebServiceConfig, WebServiceFactory};
use super::error::ErrorRenderer;
use super::extract::FromRequest;
use super::guard::Guard;
use super::handler::Handler;
use super::request::WebRequest;
use super::responder::Responder;
use super::response::WebResponse;
use super::route::{IntoRoutes, Route, RouteService};
use super::{app::Filter, app::Stack, types::Data};
use super::{app::Filter, app::Stack, guard::Guard, types::State};
type HttpService<Err: ErrorRenderer> =
BoxService<WebRequest<Err>, WebResponse, Err::Container>;
@ -53,7 +52,7 @@ pub struct Resource<Err: ErrorRenderer, M = Identity, T = Filter<Err>> {
rdef: Vec<String>,
name: Option<String>,
routes: Vec<Route<Err>>,
data: Option<Extensions>,
state: Option<Extensions>,
guards: Vec<Box<dyn Guard>>,
default: Rc<RefCell<Option<Rc<HttpNewService<Err>>>>>,
}
@ -67,7 +66,7 @@ impl<Err: ErrorRenderer> Resource<Err> {
middleware: Identity,
filter: pipeline_factory(Filter::new()),
guards: Vec::new(),
data: None,
state: None,
default: Rc::new(RefCell::new(None)),
}
}
@ -170,10 +169,10 @@ where
self
}
/// Provide resource specific data. This method allows to add extractor
/// configuration or specific state available via `Data<T>` extractor.
/// Provided data is available for all routes registered for the current resource.
/// Resource data overrides data registered by `App::data()` method.
/// Provide resource specific state. This method allows to add extractor
/// configuration or specific state available via `State<T>` extractor.
/// Provided state is available for all routes registered for the current resource.
/// Resource state overrides state registered by `App::state()` method.
///
/// ```rust
/// use ntex::web::{self, App, FromRequest};
@ -187,7 +186,7 @@ where
/// let app = App::new().service(
/// web::resource("/index.html")
/// // limit size of the payload
/// .app_data(web::types::PayloadConfig::new(4096))
/// .app_state(web::types::PayloadConfig::new(4096))
/// .route(
/// web::get()
/// // register handler
@ -195,18 +194,18 @@ where
/// ));
/// }
/// ```
pub fn data<D: 'static>(self, data: D) -> Self {
self.app_data(Data::new(data))
pub fn state<D: 'static>(self, st: D) -> Self {
self.app_state(State::new(st))
}
/// Set or override application data.
/// Set or override application state.
///
/// This method overrides data stored with [`App::app_data()`](#method.app_data)
pub fn app_data<D: 'static>(mut self, data: D) -> Self {
if self.data.is_none() {
self.data = Some(Extensions::new());
/// This method overrides state stored with [`App::app_state()`](#method.app_state)
pub fn app_state<D: 'static>(mut self, st: D) -> Self {
if self.state.is_none() {
self.state = Some(Extensions::new());
}
self.data.as_mut().unwrap().insert(data);
self.state.as_mut().unwrap().insert(st);
self
}
@ -273,7 +272,7 @@ where
guards: self.guards,
routes: self.routes,
default: self.default,
data: self.data,
state: self.state,
}
}
@ -293,7 +292,7 @@ where
guards: self.guards,
routes: self.routes,
default: self.default,
data: self.data,
state: self.state,
}
}
@ -344,13 +343,13 @@ where
*rdef.name_mut() = name.clone();
}
// custom app data storage
if let Some(ref mut ext) = self.data {
config.set_service_data(ext);
if let Some(ref mut ext) = self.state {
config.set_service_state(ext);
}
let router_factory = ResourceRouterFactory {
routes: self.routes,
data: self.data.map(Rc::new),
state: self.state.map(Rc::new),
default: self.default,
};
@ -388,7 +387,7 @@ where
) -> ResourceServiceFactory<Err, M, PipelineFactory<T, WebRequest<Err>>> {
let router_factory = ResourceRouterFactory {
routes: self.routes,
data: self.data.map(Rc::new),
state: self.state.map(Rc::new),
default: self.default,
};
@ -507,7 +506,7 @@ where
struct ResourceRouterFactory<Err: ErrorRenderer> {
routes: Vec<Route<Err>>,
data: Option<Rc<Extensions>>,
state: Option<Rc<Extensions>>,
default: Rc<RefCell<Option<Rc<HttpNewService<Err>>>>>,
}
@ -519,7 +518,7 @@ impl<Err: ErrorRenderer> ServiceFactory<WebRequest<Err>> for ResourceRouterFacto
type Future = Pin<Box<dyn Future<Output = Result<Self::Service, Self::InitError>>>>;
fn new_service(&self, _: ()) -> Self::Future {
let data = self.data.clone();
let state = self.state.clone();
let routes = self.routes.iter().map(|route| route.service()).collect();
let default_fut = self.default.borrow().as_ref().map(|f| f.new_service(()));
@ -532,7 +531,7 @@ impl<Err: ErrorRenderer> ServiceFactory<WebRequest<Err>> for ResourceRouterFacto
Ok(ResourceRouter {
routes,
data,
state,
default,
})
})
@ -541,7 +540,7 @@ impl<Err: ErrorRenderer> ServiceFactory<WebRequest<Err>> for ResourceRouterFacto
struct ResourceRouter<Err: ErrorRenderer> {
routes: Vec<RouteService<Err>>,
data: Option<Rc<Extensions>>,
state: Option<Rc<Extensions>>,
default: Option<HttpService<Err>>,
}
@ -561,8 +560,8 @@ impl<Err: ErrorRenderer> Service<WebRequest<Err>> for ResourceRouter<Err> {
fn call(&self, mut req: WebRequest<Err>) -> Self::Future {
for route in self.routes.iter() {
if route.check(&mut req) {
if let Some(ref data) = self.data {
req.set_data_container(data.clone());
if let Some(ref state) = self.state {
req.set_state_container(state.clone());
}
return Either::Right(route.call(req));
}
@ -745,21 +744,21 @@ mod tests {
}
#[crate::rt_test]
async fn test_data() {
async fn test_state() {
let srv = init_service(
App::new()
.data(1i32)
.data(1usize)
.app_data(web::types::Data::new('-'))
.state(1i32)
.state(1usize)
.app_state(web::types::State::new('-'))
.service(
web::resource("/test")
.data(10usize)
.app_data(web::types::Data::new('*'))
.state(10usize)
.app_state(web::types::State::new('*'))
.guard(guard::Get())
.to(
|data1: web::types::Data<usize>,
data2: web::types::Data<char>,
data3: web::types::Data<i32>| {
|data1: web::types::State<usize>,
data2: web::types::State<char>,
data3: web::types::State<i32>| {
assert_eq!(**data1, 10);
assert_eq!(**data2, '*');
assert_eq!(**data3, 1);

View file

@ -20,7 +20,7 @@ use super::response::WebResponse;
use super::rmap::ResourceMap;
use super::route::Route;
use super::service::{AppServiceFactory, ServiceFactoryWrapper};
use super::types::Data;
use super::types::State;
type Guards = Vec<Box<dyn Guard>>;
type HttpService<Err: ErrorRenderer> =
@ -63,7 +63,7 @@ pub struct Scope<Err: ErrorRenderer, M = Identity, T = Filter<Err>> {
middleware: M,
filter: PipelineFactory<T, WebRequest<Err>>,
rdef: Vec<String>,
data: Option<Extensions>,
state: Option<Extensions>,
services: Vec<Box<dyn AppServiceFactory<Err>>>,
guards: Vec<Box<dyn Guard>>,
default: Rc<RefCell<Option<Rc<HttpNewService<Err>>>>>,
@ -78,7 +78,7 @@ impl<Err: ErrorRenderer> Scope<Err> {
middleware: Identity,
filter: pipeline_factory(Filter::new()),
rdef: path.patterns(),
data: None,
state: None,
guards: Vec::new(),
services: Vec::new(),
default: Rc::new(RefCell::new(None)),
@ -123,44 +123,44 @@ where
self
}
/// Set or override application data. Application data could be accessed
/// by using `Data<T>` extractor where `T` is data type.
/// Set or override application state. Application state could be accessed
/// by using `State<T>` extractor where `T` is state type.
///
/// ```rust
/// use std::cell::Cell;
/// use ntex::web::{self, App, HttpResponse};
///
/// struct MyData {
/// struct MyState {
/// counter: Cell<usize>,
/// }
///
/// async fn index(data: web::types::Data<MyData>) -> HttpResponse {
/// data.counter.set(data.counter.get() + 1);
/// async fn index(st: web::types::State<MyState>) -> HttpResponse {
/// st.counter.set(st.counter.get() + 1);
/// HttpResponse::Ok().into()
/// }
///
/// fn main() {
/// let app = App::new().service(
/// web::scope("/app")
/// .data(MyData{ counter: Cell::new(0) })
/// .state(MyState{ counter: Cell::new(0) })
/// .service(
/// web::resource("/index.html").route(
/// web::get().to(index)))
/// );
/// }
/// ```
pub fn data<D: 'static>(self, data: D) -> Self {
self.app_data(Data::new(data))
pub fn state<D: 'static>(self, st: D) -> Self {
self.app_state(State::new(st))
}
/// Set or override application data.
/// Set or override application state.
///
/// This method overrides data stored with [`App::app_data()`](#method.app_data)
pub fn app_data<D: 'static>(mut self, data: D) -> Self {
if self.data.is_none() {
self.data = Some(Extensions::new());
/// This method overrides state stored with [`App::app_state()`](#method.app_state)
pub fn app_state<D: 'static>(mut self, st: D) -> Self {
if self.state.is_none() {
self.state = Some(Extensions::new());
}
self.data.as_mut().unwrap().insert(data);
self.state.as_mut().unwrap().insert(st);
self
}
@ -209,14 +209,14 @@ where
self.services.extend(cfg.services);
self.external.extend(cfg.external);
if !cfg.data.is_empty() {
let mut data = self.data.unwrap_or_else(Extensions::new);
if !cfg.state.is_empty() {
let mut state = self.state.unwrap_or_else(Extensions::new);
for value in cfg.data.iter() {
value.create(&mut data);
for value in cfg.state.iter() {
value.create(&mut state);
}
self.data = Some(data);
self.state = Some(state);
}
self
}
@ -338,7 +338,7 @@ where
filter: self.filter.and_then(filter.into_factory()),
middleware: self.middleware,
rdef: self.rdef,
data: self.data,
state: self.state,
guards: self.guards,
services: self.services,
default: self.default,
@ -362,7 +362,7 @@ where
middleware: Stack::new(self.middleware, mw),
filter: self.filter,
rdef: self.rdef,
data: self.data,
state: self.state,
guards: self.guards,
services: self.services,
default: self.default,
@ -405,13 +405,13 @@ where
}
// custom app data storage
if let Some(ref mut ext) = self.data {
config.set_service_data(ext);
if let Some(ref mut ext) = self.state {
config.set_service_state(ext);
}
// complete scope pipeline creation
let router_factory = ScopeRouterFactory {
data: self.data.take().map(Rc::new),
state: self.state.take().map(Rc::new),
default: self.default.clone(),
case_insensitive: self.case_insensitive,
services: Rc::new(
@ -560,7 +560,7 @@ where
}
struct ScopeRouterFactory<Err: ErrorRenderer> {
data: Option<Rc<Extensions>>,
state: Option<Rc<Extensions>>,
services: Rc<Vec<(ResourceDef, HttpNewService<Err>, RefCell<Option<Guards>>)>>,
default: Rc<RefCell<Option<Rc<HttpNewService<Err>>>>>,
case_insensitive: bool,
@ -576,7 +576,7 @@ impl<Err: ErrorRenderer> ServiceFactory<WebRequest<Err>> for ScopeRouterFactory<
fn new_service(&self, _: ()) -> Self::Future {
let services = self.services.clone();
let case_insensitive = self.case_insensitive;
let data = self.data.clone();
let state = self.state.clone();
let default_fut = self
.default
.borrow()
@ -601,7 +601,7 @@ impl<Err: ErrorRenderer> ServiceFactory<WebRequest<Err>> for ScopeRouterFactory<
};
Ok(ScopeRouter {
data,
state,
default,
router: router.finish(),
})
@ -610,7 +610,7 @@ impl<Err: ErrorRenderer> ServiceFactory<WebRequest<Err>> for ScopeRouterFactory<
}
struct ScopeRouter<Err: ErrorRenderer> {
data: Option<Rc<Extensions>>,
state: Option<Rc<Extensions>>,
router: Router<HttpService<Err>, Vec<Box<dyn Guard>>>,
default: Option<HttpService<Err>>,
}
@ -638,8 +638,8 @@ impl<Err: ErrorRenderer> Service<WebRequest<Err>> for ScopeRouter<Err> {
});
if let Some((srv, _info)) = res {
if let Some(ref data) = self.data {
req.set_data_container(data.clone());
if let Some(ref state) = self.state {
req.set_state_container(state.clone());
}
Either::Left(srv.call(req))
} else if let Some(ref default) = self.default {
@ -1195,10 +1195,10 @@ mod tests {
#[crate::rt_test]
async fn test_override_data() {
let srv = init_service(App::new().data(1usize).service(
web::scope("app").data(10usize).route(
let srv = init_service(App::new().state(1usize).service(
web::scope("app").state(10usize).route(
"/t",
web::get().to(|data: web::types::Data<usize>| {
web::get().to(|data: web::types::State<usize>| {
assert_eq!(**data, 10);
async { HttpResponse::Ok() }
}),
@ -1214,17 +1214,19 @@ mod tests {
#[crate::rt_test]
async fn test_override_app_data() {
let srv = init_service(
App::new().app_data(web::types::Data::new(1usize)).service(
web::scope("app")
.app_data(web::types::Data::new(10usize))
.route(
"/t",
web::get().to(|data: web::types::Data<usize>| {
assert_eq!(**data, 10);
async { HttpResponse::Ok() }
}),
),
),
App::new()
.app_state(web::types::State::new(1usize))
.service(
web::scope("app")
.app_state(web::types::State::new(10usize))
.route(
"/t",
web::get().to(|data: web::types::State<usize>| {
assert_eq!(**data, 10);
async { HttpResponse::Ok() }
}),
),
),
)
.await;
@ -1236,7 +1238,7 @@ mod tests {
#[crate::rt_test]
async fn test_scope_config() {
let srv = init_service(App::new().service(web::scope("/app").configure(|s| {
s.data("teat");
s.state("teat");
s.route("/path1", web::get().to(|| async { HttpResponse::Ok() }));
})))
.await;

View file

@ -11,7 +11,7 @@ use super::guard::Guard;
use super::request::WebRequest;
use super::response::WebResponse;
use super::rmap::ResourceMap;
use super::types::data::DataFactory;
use super::types::state::StateFactory;
pub trait WebServiceFactory<Err: ErrorRenderer> {
fn register(self, config: &mut WebServiceConfig<Err>);
@ -60,7 +60,7 @@ pub struct WebServiceConfig<Err: ErrorRenderer> {
Option<Guards>,
Option<Rc<ResourceMap>>,
)>,
service_data: Rc<Vec<Box<dyn DataFactory>>>,
service_state: Rc<Vec<Box<dyn StateFactory>>>,
}
impl<Err: ErrorRenderer> WebServiceConfig<Err> {
@ -68,12 +68,12 @@ impl<Err: ErrorRenderer> WebServiceConfig<Err> {
pub(crate) fn new(
config: AppConfig,
default: Rc<HttpServiceFactory<Err>>,
service_data: Rc<Vec<Box<dyn DataFactory>>>,
service_state: Rc<Vec<Box<dyn StateFactory>>>,
) -> Self {
WebServiceConfig {
config,
default,
service_data,
service_state,
root: true,
services: Vec::new(),
}
@ -104,7 +104,7 @@ impl<Err: ErrorRenderer> WebServiceConfig<Err> {
default: self.default.clone(),
services: Vec::new(),
root: false,
service_data: self.service_data.clone(),
service_state: self.service_state.clone(),
}
}
@ -118,12 +118,12 @@ impl<Err: ErrorRenderer> WebServiceConfig<Err> {
self.default.clone()
}
/// Set global route data
pub fn set_service_data(&self, extensions: &mut Extensions) -> bool {
for f in self.service_data.iter() {
/// Set global route state
pub fn set_service_state(&self, extensions: &mut Extensions) -> bool {
for f in self.service_state.iter() {
f.create(extensions);
}
!self.service_data.is_empty()
!self.service_state.is_empty()
}
/// Register http service

View file

@ -304,7 +304,7 @@ pub struct TestRequest {
config: AppConfig,
path: Path<Uri>,
peer_addr: Option<SocketAddr>,
app_data: Extensions,
app_state: Extensions,
}
impl Default for TestRequest {
@ -315,7 +315,7 @@ impl Default for TestRequest {
config: AppConfig::default(),
path: Path::new(Uri::default()),
peer_addr: None,
app_data: Extensions::new(),
app_state: Extensions::new(),
}
}
}
@ -439,8 +439,8 @@ impl TestRequest {
/// Set application data. This is equivalent of `App::data()` method
/// for testing purpose.
pub fn data<T: 'static>(mut self, data: T) -> Self {
self.app_data.insert(data);
pub fn state<T: 'static>(mut self, data: T) -> Self {
self.app_state.insert(data);
self
}
@ -467,7 +467,7 @@ impl TestRequest {
payload,
Rc::new(self.rmap),
self.config.clone(),
Rc::new(self.app_data),
Rc::new(self.app_state),
HttpRequestPool::create(),
))
}
@ -488,7 +488,7 @@ impl TestRequest {
payload,
Rc::new(self.rmap),
self.config.clone(),
Rc::new(self.app_data),
Rc::new(self.app_state),
HttpRequestPool::create(),
)
}
@ -504,7 +504,7 @@ impl TestRequest {
Payload::None,
Rc::new(self.rmap),
self.config.clone(),
Rc::new(self.app_data),
Rc::new(self.app_state),
HttpRequestPool::create(),
);
@ -980,7 +980,7 @@ mod tests {
.version(Version::HTTP_2)
.header(header::DATE, "some date")
.param("test", "123")
.data(web::types::Data::new(20u64))
.state(web::types::State::new(20u64))
.peer_addr("127.0.0.1:8081".parse().unwrap())
.to_http_request();
assert!(req.headers().contains_key(header::CONTENT_TYPE));
@ -988,7 +988,7 @@ mod tests {
// assert_eq!(req.peer_addr(), Some("127.0.0.1:8081".parse().unwrap()));
assert_eq!(&req.match_info()["test"], "123");
assert_eq!(req.version(), Version::HTTP_2);
let data = req.app_data::<web::types::Data<u64>>().unwrap();
let data = req.app_state::<web::types::State<u64>>().unwrap();
assert_eq!(*data.get_ref(), 20);
assert_eq!(format!("{:?}", StreamType::Tcp), "StreamType::Tcp");
@ -1152,13 +1152,13 @@ mod tests {
}
#[crate::rt_test]
async fn test_server_data() {
async fn handler(data: web::types::Data<usize>) -> crate::http::ResponseBuilder {
async fn test_server_state() {
async fn handler(data: web::types::State<usize>) -> crate::http::ResponseBuilder {
assert_eq!(**data, 10);
HttpResponse::Ok()
}
let app = init_service(App::new().data(10usize).service(
let app = init_service(App::new().state(10usize).service(
web::resource("/index.html").to(crate::web::dev::__assert_handler1(handler)),
))
.await;

View file

@ -106,7 +106,7 @@ where
#[inline]
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
let limit = req
.app_data::<FormConfig>()
.app_state::<FormConfig>()
.map(|c| c.limit)
.unwrap_or(16384);
@ -172,7 +172,7 @@ where
/// let app = App::new().service(
/// web::resource("/index.html")
/// // change `Form` extractor configuration
/// .app_data(
/// .app_state(
/// web::types::FormConfig::default().limit(4097)
/// )
/// .route(web::get().to(index))

View file

@ -170,7 +170,7 @@ where
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
let req2 = req.clone();
let (limit, ctype) = req
.app_data::<JsonConfig>()
.app_state::<JsonConfig>()
.map(|c| (c.limit, c.content_type.clone()))
.unwrap_or((32768, None));
@ -210,7 +210,7 @@ where
/// fn main() {
/// let app = App::new().service(
/// web::resource("/index.html")
/// .app_data(
/// .app_state(
/// // change json extractor configuration
/// web::types::JsonConfig::default()
/// .limit(4096)
@ -458,7 +458,7 @@ mod tests {
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().limit(10))
.state(JsonConfig::default().limit(10))
.to_http_parts();
let s = from_request::<Json<MyObject>>(&req, &mut pl).await;
@ -529,7 +529,7 @@ mod tests {
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().limit(4096))
.state(JsonConfig::default().limit(4096))
.to_http_parts();
let s = from_request::<Json<MyObject>>(&req, &mut pl).await;
@ -547,7 +547,7 @@ mod tests {
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().content_type(|mime: mime::Mime| {
.state(JsonConfig::default().content_type(|mime: mime::Mime| {
mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN
}))
.to_http_parts();
@ -567,7 +567,7 @@ mod tests {
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().content_type(|mime: mime::Mime| {
.state(JsonConfig::default().content_type(|mime: mime::Mime| {
mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN
}))
.to_http_parts();

View file

@ -1,15 +1,19 @@
//! Extractor types
pub(in crate::web) mod data;
pub(in crate::web) mod form;
pub(in crate::web) mod json;
mod path;
pub(in crate::web) mod payload;
mod query;
pub(in crate::web) mod state;
pub use self::data::Data;
pub use self::form::{Form, FormConfig};
pub use self::json::{Json, JsonConfig};
pub use self::path::Path;
pub use self::payload::{Payload, PayloadConfig};
pub use self::query::Query;
pub use self::state::State;
#[deprecated]
#[doc(hidden)]
pub type Data<T> = State<T>;

View file

@ -22,7 +22,7 @@ use crate::web::{FromRequest, HttpRequest};
/// async fn index(mut body: web::types::Payload) -> Result<HttpResponse, error::PayloadError>
/// {
/// let mut bytes = BytesMut::new();
/// while let Some(item) = ntex::util::next(&mut body).await {
/// while let Some(item) = ntex::util::stream_recv(&mut body).await {
/// bytes.extend_from_slice(&item?);
/// }
///
@ -90,7 +90,7 @@ impl Stream for Payload {
/// async fn index(mut body: web::types::Payload) -> Result<HttpResponse, error::PayloadError>
/// {
/// let mut bytes = BytesMut::new();
/// while let Some(item) = ntex::util::next(&mut body).await {
/// while let Some(item) = ntex::util::stream_recv(&mut body).await {
/// bytes.extend_from_slice(&item?);
/// }
///
@ -149,7 +149,7 @@ impl<Err: ErrorRenderer> FromRequest<Err> for Bytes {
#[inline]
fn from_request(req: &HttpRequest, payload: &mut crate::http::Payload) -> Self::Future {
let tmp;
let cfg = if let Some(cfg) = req.app_data::<PayloadConfig>() {
let cfg = if let Some(cfg) = req.app_state::<PayloadConfig>() {
cfg
} else {
tmp = PayloadConfig::default();
@ -186,7 +186,7 @@ impl<Err: ErrorRenderer> FromRequest<Err> for Bytes {
/// fn main() {
/// let app = App::new().service(
/// web::resource("/index.html")
/// .app_data(
/// .app_state(
/// web::types::PayloadConfig::new(4096) // <- limit size of the payload
/// )
/// .route(web::get().to(index)) // <- register handler with extractor params
@ -203,7 +203,7 @@ impl<Err: ErrorRenderer> FromRequest<Err> for String {
#[inline]
fn from_request(req: &HttpRequest, payload: &mut crate::http::Payload) -> Self::Future {
let tmp;
let cfg = if let Some(cfg) = req.app_data::<PayloadConfig>() {
let cfg = if let Some(cfg) = req.app_state::<PayloadConfig>() {
cfg
} else {
tmp = PayloadConfig::default();
@ -460,7 +460,7 @@ mod tests {
let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "11")
.set_payload(Bytes::from_static(b"hello=world"))
.data(PayloadConfig::default().mimetype(mime::APPLICATION_JSON))
.state(PayloadConfig::default().mimetype(mime::APPLICATION_JSON))
.to_http_parts();
assert!(from_request::<Bytes>(&req, &mut pl).await.is_err());
}
@ -483,7 +483,7 @@ mod tests {
let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "11")
.set_payload(Bytes::from_static(b"hello=world"))
.data(PayloadConfig::default().mimetype(mime::APPLICATION_JSON))
.state(PayloadConfig::default().mimetype(mime::APPLICATION_JSON))
.to_http_parts();
assert!(from_request::<String>(&req, &mut pl).await.is_err());
}

View file

@ -7,69 +7,69 @@ use crate::web::extract::FromRequest;
use crate::web::httprequest::HttpRequest;
/// Application data factory
pub(crate) trait DataFactory {
pub(crate) trait StateFactory {
fn create(&self, extensions: &mut Extensions) -> bool;
}
/// Application data.
/// Application state.
///
/// Application data is an arbitrary data attached to the app.
/// Application data is available to all routes and could be added
/// Application state is an arbitrary data attached to the app.
/// Application state is available to all routes and could be added
/// during application configuration process
/// with `App::data()` method.
/// with `App::state()` method.
///
/// Application data could be accessed by using `Data<T>`
/// extractor where `T` is data type.
/// Application state could be accessed by using `State<T>`
/// extractor where `T` is state type.
///
/// **Note**: http server accepts an application factory rather than
/// an application instance. Http server constructs an application
/// instance for each thread, thus application data must be constructed
/// multiple times. If you want to share data between different
/// multiple times. If you want to share state between different
/// threads, a shareable object should be used, e.g. `Send + Sync`. Application
/// data does not need to be `Send` or `Sync`. Internally `Data` type
/// uses `Arc`. if your data implements `Send` + `Sync` traits you can
/// use `web::types::Data::new()` and avoid double `Arc`.
/// state does not need to be `Send` or `Sync`. Internally `State` type
/// uses `Arc`. if your state implements `Send` + `Sync` traits you can
/// use `web::types::State::new()` and avoid double `Arc`.
///
/// If route data is not set for a handler, using `Data<T>` extractor would
/// If state is not set for a handler, using `State<T>` extractor would
/// cause *Internal Server Error* response.
///
/// ```rust
/// use std::sync::Mutex;
/// use ntex::web::{self, App, HttpResponse};
///
/// struct MyData {
/// struct MyState {
/// counter: usize,
/// }
///
/// /// Use `Data<T>` extractor to access data in handler.
/// async fn index(data: web::types::Data<Mutex<MyData>>) -> HttpResponse {
/// let mut data = data.lock().unwrap();
/// /// Use `State<T>` extractor to access data in handler.
/// async fn index(st: web::types::State<Mutex<MyState>>) -> HttpResponse {
/// let mut data = st.lock().unwrap();
/// data.counter += 1;
/// HttpResponse::Ok().into()
/// }
///
/// fn main() {
/// let data = web::types::Data::new(Mutex::new(MyData{ counter: 0 }));
/// let st = web::types::State::new(Mutex::new(MyState{ counter: 0 }));
///
/// let app = App::new()
/// // Store `MyData` in application storage.
/// .app_data(data.clone())
/// // Store `MyState` in application storage.
/// .app_state(st.clone())
/// .service(
/// web::resource("/index.html").route(
/// web::get().to(index)));
/// }
/// ```
#[derive(Debug)]
pub struct Data<T>(Arc<T>);
pub struct State<T>(Arc<T>);
impl<T> Data<T> {
/// Create new `Data` instance.
impl<T> State<T> {
/// Create new `State` instance.
///
/// Internally `Data` type uses `Arc`. if your data implements
/// `Send` + `Sync` traits you can use `web::types::Data::new()` and
/// Internally `State` type uses `Arc`. if your state implements
/// `Send` + `Sync` traits you can use `web::types::State::new()` and
/// avoid double `Arc`.
pub fn new(state: T) -> Data<T> {
Data(Arc::new(state))
pub fn new(state: T) -> State<T> {
State(Arc::new(state))
}
/// Get reference to inner app data.
@ -83,7 +83,7 @@ impl<T> Data<T> {
}
}
impl<T> Deref for Data<T> {
impl<T> Deref for State<T> {
type Target = Arc<T>;
fn deref(&self) -> &Arc<T> {
@ -91,19 +91,19 @@ impl<T> Deref for Data<T> {
}
}
impl<T> Clone for Data<T> {
fn clone(&self) -> Data<T> {
Data(self.0.clone())
impl<T> Clone for State<T> {
fn clone(&self) -> State<T> {
State(self.0.clone())
}
}
impl<T: 'static, E: ErrorRenderer> FromRequest<E> for Data<T> {
impl<T: 'static, E: ErrorRenderer> FromRequest<E> for State<T> {
type Error = DataExtractorError;
type Future = Ready<Self, Self::Error>;
#[inline]
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
if let Some(st) = req.app_data::<Data<T>>() {
if let Some(st) = req.app_state::<State<T>>() {
Ready::Ok(st.clone())
} else {
log::debug!(
@ -116,10 +116,10 @@ impl<T: 'static, E: ErrorRenderer> FromRequest<E> for Data<T> {
}
}
impl<T: 'static> DataFactory for Data<T> {
impl<T: 'static> StateFactory for State<T> {
fn create(&self, extensions: &mut Extensions) -> bool {
if !extensions.contains::<Data<T>>() {
extensions.insert(Data(self.0.clone()));
if !extensions.contains::<State<T>>() {
extensions.insert(State(self.0.clone()));
true
} else {
false
@ -139,8 +139,8 @@ mod tests {
#[crate::rt_test]
async fn test_data_extractor() {
let srv = init_service(App::new().data("TEST".to_string()).service(
web::resource("/").to(|data: web::types::Data<String>| async move {
let srv = init_service(App::new().state("TEST".to_string()).service(
web::resource("/").to(|data: web::types::State<String>| async move {
assert_eq!(data.to_lowercase(), "test");
HttpResponse::Ok()
}),
@ -152,9 +152,9 @@ mod tests {
assert_eq!(resp.status(), StatusCode::OK);
let srv = init_service(
App::new().data(10u32).service(
App::new().state(10u32).service(
web::resource("/")
.to(|_: web::types::Data<usize>| async { HttpResponse::Ok() }),
.to(|_: web::types::State<usize>| async { HttpResponse::Ok() }),
),
)
.await;
@ -166,9 +166,9 @@ mod tests {
#[crate::rt_test]
async fn test_app_data_extractor() {
let srv = init_service(
App::new().app_data(Data::new(10usize)).service(
App::new().app_state(State::new(10usize)).service(
web::resource("/")
.to(|_: web::types::Data<usize>| async { HttpResponse::Ok() }),
.to(|_: web::types::State<usize>| async { HttpResponse::Ok() }),
),
)
.await;
@ -178,9 +178,9 @@ mod tests {
assert_eq!(resp.status(), StatusCode::OK);
let srv = init_service(
App::new().app_data(Data::new(10u32)).service(
App::new().app_state(State::new(10u32)).service(
web::resource("/")
.to(|_: web::types::Data<usize>| async { HttpResponse::Ok() }),
.to(|_: web::types::State<usize>| async { HttpResponse::Ok() }),
),
)
.await;
@ -191,21 +191,22 @@ mod tests {
#[crate::rt_test]
async fn test_route_data_extractor() {
let srv = init_service(App::new().service(web::resource("/").data(10usize).route(
web::get().to(|data: web::types::Data<usize>| async move {
let _ = data.clone();
HttpResponse::Ok()
}),
)))
.await;
let srv =
init_service(App::new().service(web::resource("/").state(10usize).route(
web::get().to(|data: web::types::State<usize>| async move {
let _ = data.clone();
HttpResponse::Ok()
}),
)))
.await;
let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
// different type
let srv = init_service(App::new().service(web::resource("/").data(10u32).route(
web::get().to(|_: web::types::Data<usize>| async { HttpResponse::Ok() }),
let srv = init_service(App::new().service(web::resource("/").state(10u32).route(
web::get().to(|_: web::types::State<usize>| async { HttpResponse::Ok() }),
)))
.await;
let req = TestRequest::default().to_request();
@ -215,9 +216,9 @@ mod tests {
#[crate::rt_test]
async fn test_override_data() {
let srv = init_service(App::new().data(1usize).service(
web::resource("/").data(10usize).route(web::get().to(
|data: web::types::Data<usize>| async move {
let srv = init_service(App::new().state(1usize).service(
web::resource("/").state(10usize).route(web::get().to(
|data: web::types::State<usize>| async move {
assert_eq!(**data, 10);
let _ = data.clone();
HttpResponse::Ok()
@ -265,8 +266,8 @@ mod tests {
let data = data.clone();
App::new()
.data(data)
.service(web::resource("/").to(|_data: Data<TestData>| async { "ok" }))
.state(data)
.service(web::resource("/").to(|_data: State<TestData>| async { "ok" }))
});
assert!(srv.get("/").send().await.unwrap().status().is_success());

View file

@ -680,7 +680,7 @@ async fn test_brotli_encoding_large() {
let srv = test::server_with(test::config().h1(), || {
App::new().service(
web::resource("/")
.app_data(web::types::PayloadConfig::new(320_000))
.app_state(web::types::PayloadConfig::new(320_000))
.route(web::to(move |body: Bytes| async {
HttpResponse::Ok().streaming(TestBody::new(body, 10240))
})),