1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-24 08:22:59 +01:00

rename State to a Data

This commit is contained in:
Nikolay Kim 2019-03-16 20:17:27 -07:00
parent d93fe157b9
commit b1e267bce4
4 changed files with 74 additions and 75 deletions

View File

@ -12,6 +12,7 @@ use futures::IntoFuture;
use crate::app_service::{AppChain, AppEntry, AppInit, AppRouting, AppRoutingFactory}; use crate::app_service::{AppChain, AppEntry, AppInit, AppRouting, AppRoutingFactory};
use crate::config::{AppConfig, AppConfigInner}; use crate::config::{AppConfig, AppConfigInner};
use crate::data::{Data, DataFactory};
use crate::dev::{PayloadStream, ResourceDef}; use crate::dev::{PayloadStream, ResourceDef};
use crate::error::Error; use crate::error::Error;
use crate::resource::Resource; use crate::resource::Resource;
@ -20,7 +21,6 @@ use crate::service::{
HttpServiceFactory, ServiceFactory, ServiceFactoryWrapper, ServiceRequest, HttpServiceFactory, ServiceFactory, ServiceFactoryWrapper, ServiceRequest,
ServiceResponse, ServiceResponse,
}; };
use crate::state::{State, StateFactory};
type HttpNewService<P> = type HttpNewService<P> =
BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>; BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
@ -32,18 +32,17 @@ where
T: NewService<Request = ServiceRequest, Response = ServiceRequest<P>>, T: NewService<Request = ServiceRequest, Response = ServiceRequest<P>>,
{ {
chain: T, chain: T,
state: Vec<Box<StateFactory>>, data: Vec<Box<DataFactory>>,
config: AppConfigInner, config: AppConfigInner,
_t: PhantomData<(P,)>, _t: PhantomData<(P,)>,
} }
impl App<PayloadStream, AppChain> { impl App<PayloadStream, AppChain> {
/// Create application builder with empty state. Application can /// Create application builder. Application can be configured with a builder-like pattern.
/// be configured with a builder-like pattern.
pub fn new() -> Self { pub fn new() -> Self {
App { App {
chain: AppChain, chain: AppChain,
state: Vec::new(), data: Vec::new(),
config: AppConfigInner::default(), config: AppConfigInner::default(),
_t: PhantomData, _t: PhantomData,
} }
@ -60,51 +59,51 @@ where
InitError = (), InitError = (),
>, >,
{ {
/// Set application state. Applicatin state could be accessed /// Set application data. Applicatin data could be accessed
/// by using `State<T>` extractor where `T` is state type. /// by using `Data<T>` extractor where `T` is data type.
/// ///
/// **Note**: http server accepts an application factory rather than /// **Note**: http server accepts an application factory rather than
/// an application instance. Http server constructs an application /// an application instance. Http server constructs an application
/// instance for each thread, thus application state must be constructed /// instance for each thread, thus application data must be constructed
/// multiple times. If you want to share state between different /// multiple times. If you want to share data between different
/// threads, a shared object should be used, e.g. `Arc`. Application /// threads, a shared object should be used, e.g. `Arc`. Application
/// state does not need to be `Send` or `Sync`. /// data does not need to be `Send` or `Sync`.
/// ///
/// ```rust /// ```rust
/// use std::cell::Cell; /// use std::cell::Cell;
/// use actix_web::{web, App}; /// use actix_web::{web, App};
/// ///
/// struct MyState { /// struct MyData {
/// counter: Cell<usize>, /// counter: Cell<usize>,
/// } /// }
/// ///
/// fn index(state: web::State<MyState>) { /// fn index(data: web::Data<MyData>) {
/// state.counter.set(state.counter.get() + 1); /// data.counter.set(data.counter.get() + 1);
/// } /// }
/// ///
/// fn main() { /// fn main() {
/// let app = App::new() /// let app = App::new()
/// .state(MyState{ counter: Cell::new(0) }) /// .data(MyData{ counter: Cell::new(0) })
/// .service( /// .service(
/// web::resource("/index.html").route( /// web::resource("/index.html").route(
/// web::get().to(index))); /// web::get().to(index)));
/// } /// }
/// ``` /// ```
pub fn state<S: 'static>(mut self, state: S) -> Self { pub fn data<S: 'static>(mut self, data: S) -> Self {
self.state.push(Box::new(State::new(state))); self.data.push(Box::new(Data::new(data)));
self self
} }
/// Set application state factory. This function is /// Set application data factory. This function is
/// similar to `.state()` but it accepts state factory. State get /// similar to `.data()` but it accepts data factory. Data object get
/// constructed asynchronously during application initialization. /// constructed asynchronously during application initialization.
pub fn state_factory<F, Out>(mut self, state: F) -> Self pub fn data_factory<F, Out>(mut self, data: F) -> Self
where where
F: Fn() -> Out + 'static, F: Fn() -> Out + 'static,
Out: IntoFuture + 'static, Out: IntoFuture + 'static,
Out::Error: std::fmt::Debug, Out::Error: std::fmt::Debug,
{ {
self.state.push(Box::new(state)); self.data.push(Box::new(data));
self self
} }
@ -138,7 +137,7 @@ where
AppRouter { AppRouter {
endpoint, endpoint,
chain: self.chain, chain: self.chain,
state: self.state, data: self.data,
services: Vec::new(), services: Vec::new(),
default: None, default: None,
factory_ref: fref, factory_ref: fref,
@ -174,7 +173,7 @@ where
let chain = self.chain.and_then(chain.into_new_service()); let chain = self.chain.and_then(chain.into_new_service());
App { App {
chain, chain,
state: self.state, data: self.data,
config: self.config, config: self.config,
_t: PhantomData, _t: PhantomData,
} }
@ -183,7 +182,7 @@ where
/// Configure route for a specific path. /// Configure route for a specific path.
/// ///
/// This is a simplified version of the `App::service()` method. /// This is a simplified version of the `App::service()` method.
/// This method can not be could multiple times, in that case /// This method can be used multiple times with same path, in that case
/// multiple resources with one route would be registered for same resource path. /// multiple resources with one route would be registered for same resource path.
/// ///
/// ```rust /// ```rust
@ -223,7 +222,7 @@ where
default: None, default: None,
endpoint: AppEntry::new(fref.clone()), endpoint: AppEntry::new(fref.clone()),
factory_ref: fref, factory_ref: fref,
state: self.state, data: self.data,
config: self.config, config: self.config,
services: vec![Box::new(ServiceFactoryWrapper::new(service))], services: vec![Box::new(ServiceFactoryWrapper::new(service))],
external: Vec::new(), external: Vec::new(),
@ -233,7 +232,7 @@ where
/// Set server host name. /// Set server host name.
/// ///
/// Host name is used by application router aa a hostname for url /// Host name is used by application router as a hostname for url
/// generation. Check [ConnectionInfo](./dev/struct.ConnectionInfo. /// generation. Check [ConnectionInfo](./dev/struct.ConnectionInfo.
/// html#method.host) documentation for more information. /// html#method.host) documentation for more information.
/// ///
@ -252,7 +251,7 @@ pub struct AppRouter<C, P, B, T> {
services: Vec<Box<ServiceFactory<P>>>, services: Vec<Box<ServiceFactory<P>>>,
default: Option<Rc<HttpNewService<P>>>, default: Option<Rc<HttpNewService<P>>>,
factory_ref: Rc<RefCell<Option<AppRoutingFactory<P>>>>, factory_ref: Rc<RefCell<Option<AppRoutingFactory<P>>>>,
state: Vec<Box<StateFactory>>, data: Vec<Box<DataFactory>>,
config: AppConfigInner, config: AppConfigInner,
external: Vec<ResourceDef>, external: Vec<ResourceDef>,
_t: PhantomData<(P, B)>, _t: PhantomData<(P, B)>,
@ -344,7 +343,7 @@ where
AppRouter { AppRouter {
endpoint, endpoint,
chain: self.chain, chain: self.chain,
state: self.state, data: self.data,
services: self.services, services: self.services,
default: self.default, default: self.default,
factory_ref: self.factory_ref, factory_ref: self.factory_ref,
@ -429,7 +428,7 @@ where
fn into_new_service(self) -> AppInit<C, T, P, B> { fn into_new_service(self) -> AppInit<C, T, P, B> {
AppInit { AppInit {
chain: self.chain, chain: self.chain,
state: self.state, data: self.data,
endpoint: self.endpoint, endpoint: self.endpoint,
services: RefCell::new(self.services), services: RefCell::new(self.services),
external: RefCell::new(self.external), external: RefCell::new(self.external),
@ -489,10 +488,10 @@ mod tests {
} }
#[test] #[test]
fn test_state() { fn test_data() {
let mut srv = let mut srv =
init_service(App::new().state(10usize).service( init_service(App::new().data(10usize).service(
web::resource("/").to(|_: web::State<usize>| HttpResponse::Ok()), web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
)); ));
let req = TestRequest::default().to_request(); let req = TestRequest::default().to_request();
@ -500,8 +499,8 @@ mod tests {
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
let mut srv = let mut srv =
init_service(App::new().state(10u32).service( init_service(App::new().data(10u32).service(
web::resource("/").to(|_: web::State<usize>| HttpResponse::Ok()), web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
)); ));
let req = TestRequest::default().to_request(); let req = TestRequest::default().to_request();
let resp = block_on(srv.call(req)).unwrap(); let resp = block_on(srv.call(req)).unwrap();
@ -509,18 +508,18 @@ mod tests {
} }
#[test] #[test]
fn test_state_factory() { fn test_data_factory() {
let mut srv = let mut srv =
init_service(App::new().state_factory(|| Ok::<_, ()>(10usize)).service( init_service(App::new().data_factory(|| Ok::<_, ()>(10usize)).service(
web::resource("/").to(|_: web::State<usize>| HttpResponse::Ok()), web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
)); ));
let req = TestRequest::default().to_request(); let req = TestRequest::default().to_request();
let resp = block_on(srv.call(req)).unwrap(); let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
let mut srv = let mut srv =
init_service(App::new().state_factory(|| Ok::<_, ()>(10u32)).service( init_service(App::new().data_factory(|| Ok::<_, ()>(10u32)).service(
web::resource("/").to(|_: web::State<usize>| HttpResponse::Ok()), web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
)); ));
let req = TestRequest::default().to_request(); let req = TestRequest::default().to_request();
let resp = block_on(srv.call(req)).unwrap(); let resp = block_on(srv.call(req)).unwrap();

View File

@ -11,11 +11,11 @@ use futures::future::{ok, Either, FutureResult};
use futures::{Async, Future, Poll}; use futures::{Async, Future, Poll};
use crate::config::{AppConfig, ServiceConfig}; use crate::config::{AppConfig, ServiceConfig};
use crate::data::{DataFactory, DataFactoryResult};
use crate::error::Error; use crate::error::Error;
use crate::guard::Guard; use crate::guard::Guard;
use crate::rmap::ResourceMap; use crate::rmap::ResourceMap;
use crate::service::{ServiceFactory, ServiceRequest, ServiceResponse}; use crate::service::{ServiceFactory, ServiceRequest, ServiceResponse};
use crate::state::{StateFactory, StateFactoryResult};
type Guards = Vec<Box<Guard>>; type Guards = Vec<Box<Guard>>;
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, Error>; type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, Error>;
@ -24,7 +24,7 @@ type HttpNewService<P> =
type BoxedResponse = Box<Future<Item = ServiceResponse, Error = Error>>; type BoxedResponse = Box<Future<Item = ServiceResponse, Error = Error>>;
/// Service factory to convert `Request` to a `ServiceRequest<S>`. /// Service factory to convert `Request` to a `ServiceRequest<S>`.
/// It also executes state factories. /// It also executes data factories.
pub struct AppInit<C, T, P, B> pub struct AppInit<C, T, P, B>
where where
C: NewService<Request = ServiceRequest, Response = ServiceRequest<P>>, C: NewService<Request = ServiceRequest, Response = ServiceRequest<P>>,
@ -37,7 +37,7 @@ where
{ {
pub(crate) chain: C, pub(crate) chain: C,
pub(crate) endpoint: T, pub(crate) endpoint: T,
pub(crate) state: Vec<Box<StateFactory>>, pub(crate) data: Vec<Box<DataFactory>>,
pub(crate) config: RefCell<AppConfig>, pub(crate) config: RefCell<AppConfig>,
pub(crate) services: RefCell<Vec<Box<ServiceFactory<P>>>>, pub(crate) services: RefCell<Vec<Box<ServiceFactory<P>>>>,
pub(crate) default: Option<Rc<HttpNewService<P>>>, pub(crate) default: Option<Rc<HttpNewService<P>>>,
@ -121,7 +121,7 @@ where
chain_fut: self.chain.new_service(&()), chain_fut: self.chain.new_service(&()),
endpoint: None, endpoint: None,
endpoint_fut: self.endpoint.new_service(&()), endpoint_fut: self.endpoint.new_service(&()),
state: self.state.iter().map(|s| s.construct()).collect(), data: self.data.iter().map(|s| s.construct()).collect(),
config: self.config.borrow().clone(), config: self.config.borrow().clone(),
rmap, rmap,
_t: PhantomData, _t: PhantomData,
@ -139,7 +139,7 @@ where
chain_fut: C::Future, chain_fut: C::Future,
endpoint_fut: T::Future, endpoint_fut: T::Future,
rmap: Rc<ResourceMap>, rmap: Rc<ResourceMap>,
state: Vec<Box<StateFactoryResult>>, data: Vec<Box<DataFactoryResult>>,
config: AppConfig, config: AppConfig,
_t: PhantomData<(P, B)>, _t: PhantomData<(P, B)>,
} }
@ -165,9 +165,9 @@ where
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let mut idx = 0; let mut idx = 0;
let mut extensions = self.config.0.extensions.borrow_mut(); let mut extensions = self.config.0.extensions.borrow_mut();
while idx < self.state.len() { while idx < self.data.len() {
if let Async::Ready(_) = self.state[idx].poll_result(&mut extensions)? { if let Async::Ready(_) = self.data[idx].poll_result(&mut extensions)? {
self.state.remove(idx); self.data.remove(idx);
} else { } else {
idx += 1; idx += 1;
} }

View File

@ -8,21 +8,21 @@ use futures::{Async, Future, IntoFuture, Poll};
use crate::extract::FromRequest; use crate::extract::FromRequest;
use crate::service::ServiceFromRequest; use crate::service::ServiceFromRequest;
/// Application state factory /// Application data factory
pub(crate) trait StateFactory { pub(crate) trait DataFactory {
fn construct(&self) -> Box<StateFactoryResult>; fn construct(&self) -> Box<DataFactoryResult>;
} }
pub(crate) trait StateFactoryResult { pub(crate) trait DataFactoryResult {
fn poll_result(&mut self, extensions: &mut Extensions) -> Poll<(), ()>; fn poll_result(&mut self, extensions: &mut Extensions) -> Poll<(), ()>;
} }
/// Application state /// Application state
pub struct State<T>(Arc<T>); pub struct Data<T>(Arc<T>);
impl<T> State<T> { impl<T> Data<T> {
pub(crate) fn new(state: T) -> State<T> { pub(crate) fn new(state: T) -> Data<T> {
State(Arc::new(state)) Data(Arc::new(state))
} }
/// Get referecnce to inner state type. /// Get referecnce to inner state type.
@ -31,7 +31,7 @@ impl<T> State<T> {
} }
} }
impl<T> Deref for State<T> { impl<T> Deref for Data<T> {
type Target = T; type Target = T;
fn deref(&self) -> &T { fn deref(&self) -> &T {
@ -39,19 +39,19 @@ impl<T> Deref for State<T> {
} }
} }
impl<T> Clone for State<T> { impl<T> Clone for Data<T> {
fn clone(&self) -> State<T> { fn clone(&self) -> Data<T> {
State(self.0.clone()) Data(self.0.clone())
} }
} }
impl<T: 'static, P> FromRequest<P> for State<T> { impl<T: 'static, P> FromRequest<P> for Data<T> {
type Error = Error; type Error = Error;
type Future = Result<Self, Error>; type Future = Result<Self, Error>;
#[inline] #[inline]
fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future { fn from_request(req: &mut ServiceFromRequest<P>) -> Self::Future {
if let Some(st) = req.config().extensions().get::<State<T>>() { if let Some(st) = req.config().extensions().get::<Data<T>>() {
Ok(st.clone()) Ok(st.clone())
} else { } else {
Err(ErrorInternalServerError( Err(ErrorInternalServerError(
@ -61,37 +61,37 @@ impl<T: 'static, P> FromRequest<P> for State<T> {
} }
} }
impl<T: 'static> StateFactory for State<T> { impl<T: 'static> DataFactory for Data<T> {
fn construct(&self) -> Box<StateFactoryResult> { fn construct(&self) -> Box<DataFactoryResult> {
Box::new(StateFut { st: self.clone() }) Box::new(DataFut { st: self.clone() })
} }
} }
struct StateFut<T> { struct DataFut<T> {
st: State<T>, st: Data<T>,
} }
impl<T: 'static> StateFactoryResult for StateFut<T> { impl<T: 'static> DataFactoryResult for DataFut<T> {
fn poll_result(&mut self, extensions: &mut Extensions) -> Poll<(), ()> { fn poll_result(&mut self, extensions: &mut Extensions) -> Poll<(), ()> {
extensions.insert(self.st.clone()); extensions.insert(self.st.clone());
Ok(Async::Ready(())) Ok(Async::Ready(()))
} }
} }
impl<F, Out> StateFactory for F impl<F, Out> DataFactory for F
where where
F: Fn() -> Out + 'static, F: Fn() -> Out + 'static,
Out: IntoFuture + 'static, Out: IntoFuture + 'static,
Out::Error: std::fmt::Debug, Out::Error: std::fmt::Debug,
{ {
fn construct(&self) -> Box<StateFactoryResult> { fn construct(&self) -> Box<DataFactoryResult> {
Box::new(StateFactoryFut { Box::new(DataFactoryFut {
fut: (*self)().into_future(), fut: (*self)().into_future(),
}) })
} }
} }
struct StateFactoryFut<T, F> struct DataFactoryFut<T, F>
where where
F: Future<Item = T>, F: Future<Item = T>,
F::Error: std::fmt::Debug, F::Error: std::fmt::Debug,
@ -99,7 +99,7 @@ where
fut: F, fut: F,
} }
impl<T: 'static, F> StateFactoryResult for StateFactoryFut<T, F> impl<T: 'static, F> DataFactoryResult for DataFactoryFut<T, F>
where where
F: Future<Item = T>, F: Future<Item = T>,
F::Error: std::fmt::Debug, F::Error: std::fmt::Debug,
@ -107,7 +107,7 @@ where
fn poll_result(&mut self, extensions: &mut Extensions) -> Poll<(), ()> { fn poll_result(&mut self, extensions: &mut Extensions) -> Poll<(), ()> {
match self.fut.poll() { match self.fut.poll() {
Ok(Async::Ready(s)) => { Ok(Async::Ready(s)) => {
extensions.insert(State::new(s)); extensions.insert(Data::new(s));
Ok(Async::Ready(())) Ok(Async::Ready(()))
} }
Ok(Async::NotReady) => Ok(Async::NotReady), Ok(Async::NotReady) => Ok(Async::NotReady),

View File

@ -3,6 +3,7 @@
mod app; mod app;
mod app_service; mod app_service;
mod config; mod config;
mod data;
pub mod error; pub mod error;
mod extract; mod extract;
pub mod guard; pub mod guard;
@ -17,7 +18,6 @@ mod route;
mod scope; mod scope;
mod server; mod server;
mod service; mod service;
mod state;
pub mod test; pub mod test;
#[allow(unused_imports)] #[allow(unused_imports)]
@ -37,7 +37,6 @@ pub use crate::request::HttpRequest;
pub use crate::resource::Resource; pub use crate::resource::Resource;
pub use crate::responder::{Either, Responder}; pub use crate::responder::{Either, Responder};
pub use crate::route::Route; pub use crate::route::Route;
pub use crate::scope::Scope;
pub use crate::server::HttpServer; pub use crate::server::HttpServer;
pub mod dev { pub mod dev {
@ -77,6 +76,7 @@ pub mod dev {
} }
pub mod web { pub mod web {
//! Various types
use actix_http::{http::Method, Response}; use actix_http::{http::Method, Response};
use actix_rt::blocking; use actix_rt::blocking;
use futures::{Future, IntoFuture}; use futures::{Future, IntoFuture};
@ -91,11 +91,11 @@ pub mod web {
use crate::route::Route; use crate::route::Route;
use crate::scope::Scope; use crate::scope::Scope;
pub use crate::data::Data;
pub use crate::error::{BlockingError, Error}; pub use crate::error::{BlockingError, Error};
pub use crate::extract::{Form, Json, Path, Payload, Query}; pub use crate::extract::{Form, Json, Path, Payload, Query};
pub use crate::extract::{FormConfig, JsonConfig, PayloadConfig}; pub use crate::extract::{FormConfig, JsonConfig, PayloadConfig};
pub use crate::request::HttpRequest; pub use crate::request::HttpRequest;
pub use crate::state::State;
/// Create resource for a specific path. /// Create resource for a specific path.
/// ///