mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-27 17:52:56 +01:00
implement App::data
as App::app_data(Data::new(T)))
(#1906)
This commit is contained in:
parent
0a506bf2e9
commit
da69bb4d12
@ -12,15 +12,22 @@
|
|||||||
`ServiceRequest::from_request` would not fail and no payload would be generated [#1893]
|
`ServiceRequest::from_request` would not fail and no payload would be generated [#1893]
|
||||||
* Our `Either` type now uses `Left`/`Right` variants (instead of `A`/`B`) [#1894]
|
* Our `Either` type now uses `Left`/`Right` variants (instead of `A`/`B`) [#1894]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* Multiple calls `App::data` with the same type now keeps the latest call's data. [#1906]
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
* Public field of `web::Path` has been made private. [#1894]
|
* Public field of `web::Path` has been made private. [#1894]
|
||||||
* Public field of `web::Query` has been made private. [#1894]
|
* Public field of `web::Query` has been made private. [#1894]
|
||||||
* `TestRequest::with_header`; use `TestRequest::default().insert_header()`. [#1869]
|
* `TestRequest::with_header`; use `TestRequest::default().insert_header()`. [#1869]
|
||||||
|
* `AppService::set_service_data`; for custom HTTP service factories adding application data, use the
|
||||||
|
layered data model by calling `ServiceRequest::add_data_container` when handling
|
||||||
|
requests instead. [#1906]
|
||||||
|
|
||||||
[#1891]: https://github.com/actix/actix-web/pull/1891
|
[#1891]: https://github.com/actix/actix-web/pull/1891
|
||||||
[#1893]: https://github.com/actix/actix-web/pull/1893
|
[#1893]: https://github.com/actix/actix-web/pull/1893
|
||||||
[#1894]: https://github.com/actix/actix-web/pull/1894
|
[#1894]: https://github.com/actix/actix-web/pull/1894
|
||||||
[#1869]: https://github.com/actix/actix-web/pull/1869
|
[#1869]: https://github.com/actix/actix-web/pull/1869
|
||||||
|
[#1906]: https://github.com/actix/actix-web/pull/1906
|
||||||
|
|
||||||
|
|
||||||
## 4.0.0-beta.1 - 2021-01-07
|
## 4.0.0-beta.1 - 2021-01-07
|
||||||
|
25
src/app.rs
25
src/app.rs
@ -34,7 +34,6 @@ pub struct App<T, B> {
|
|||||||
services: Vec<Box<dyn AppServiceFactory>>,
|
services: Vec<Box<dyn AppServiceFactory>>,
|
||||||
default: Option<Rc<HttpNewService>>,
|
default: Option<Rc<HttpNewService>>,
|
||||||
factory_ref: Rc<RefCell<Option<AppRoutingFactory>>>,
|
factory_ref: Rc<RefCell<Option<AppRoutingFactory>>>,
|
||||||
data: Vec<Box<dyn DataFactory>>,
|
|
||||||
data_factories: Vec<FnDataFactory>,
|
data_factories: Vec<FnDataFactory>,
|
||||||
external: Vec<ResourceDef>,
|
external: Vec<ResourceDef>,
|
||||||
extensions: Extensions,
|
extensions: Extensions,
|
||||||
@ -48,7 +47,6 @@ impl App<AppEntry, Body> {
|
|||||||
let fref = Rc::new(RefCell::new(None));
|
let fref = Rc::new(RefCell::new(None));
|
||||||
App {
|
App {
|
||||||
endpoint: AppEntry::new(fref.clone()),
|
endpoint: AppEntry::new(fref.clone()),
|
||||||
data: Vec::new(),
|
|
||||||
data_factories: Vec::new(),
|
data_factories: Vec::new(),
|
||||||
services: Vec::new(),
|
services: Vec::new(),
|
||||||
default: None,
|
default: None,
|
||||||
@ -101,9 +99,8 @@ where
|
|||||||
/// web::resource("/index.html").route(
|
/// web::resource("/index.html").route(
|
||||||
/// web::get().to(index)));
|
/// web::get().to(index)));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn data<U: 'static>(mut self, data: U) -> Self {
|
pub fn data<U: 'static>(self, data: U) -> Self {
|
||||||
self.data.push(Box::new(Data::new(data)));
|
self.app_data(Data::new(data))
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set application data factory. This function is
|
/// Set application data factory. This function is
|
||||||
@ -157,8 +154,7 @@ where
|
|||||||
/// some of the resource's configuration could be moved to different module.
|
/// some of the resource's configuration could be moved to different module.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # extern crate actix_web;
|
/// use actix_web::{web, App, HttpResponse};
|
||||||
/// use actix_web::{web, middleware, App, HttpResponse};
|
|
||||||
///
|
///
|
||||||
/// // this function could be located in different module
|
/// // this function could be located in different module
|
||||||
/// fn config(cfg: &mut web::ServiceConfig) {
|
/// fn config(cfg: &mut web::ServiceConfig) {
|
||||||
@ -168,12 +164,9 @@ where
|
|||||||
/// );
|
/// );
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// App::new()
|
||||||
/// let app = App::new()
|
/// .configure(config) // <- register resources
|
||||||
/// .wrap(middleware::Logger::default())
|
/// .route("/index.html", web::get().to(|| HttpResponse::Ok()));
|
||||||
/// .configure(config) // <- register resources
|
|
||||||
/// .route("/index.html", web::get().to(|| HttpResponse::Ok()));
|
|
||||||
/// }
|
|
||||||
/// ```
|
/// ```
|
||||||
pub fn configure<F>(mut self, f: F) -> Self
|
pub fn configure<F>(mut self, f: F) -> Self
|
||||||
where
|
where
|
||||||
@ -181,10 +174,9 @@ where
|
|||||||
{
|
{
|
||||||
let mut cfg = ServiceConfig::new();
|
let mut cfg = ServiceConfig::new();
|
||||||
f(&mut cfg);
|
f(&mut cfg);
|
||||||
self.data.extend(cfg.data);
|
|
||||||
self.services.extend(cfg.services);
|
self.services.extend(cfg.services);
|
||||||
self.external.extend(cfg.external);
|
self.external.extend(cfg.external);
|
||||||
self.extensions.extend(cfg.extensions);
|
self.extensions.extend(cfg.app_data);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,7 +366,6 @@ where
|
|||||||
{
|
{
|
||||||
App {
|
App {
|
||||||
endpoint: apply(mw, self.endpoint),
|
endpoint: apply(mw, self.endpoint),
|
||||||
data: self.data,
|
|
||||||
data_factories: self.data_factories,
|
data_factories: self.data_factories,
|
||||||
services: self.services,
|
services: self.services,
|
||||||
default: self.default,
|
default: self.default,
|
||||||
@ -436,7 +427,6 @@ where
|
|||||||
{
|
{
|
||||||
App {
|
App {
|
||||||
endpoint: apply_fn_factory(self.endpoint, mw),
|
endpoint: apply_fn_factory(self.endpoint, mw),
|
||||||
data: self.data,
|
|
||||||
data_factories: self.data_factories,
|
data_factories: self.data_factories,
|
||||||
services: self.services,
|
services: self.services,
|
||||||
default: self.default,
|
default: self.default,
|
||||||
@ -462,7 +452,6 @@ where
|
|||||||
{
|
{
|
||||||
fn into_factory(self) -> AppInit<T, B> {
|
fn into_factory(self) -> AppInit<T, B> {
|
||||||
AppInit {
|
AppInit {
|
||||||
data_factories: self.data.into_boxed_slice().into(),
|
|
||||||
async_data_factories: self.data_factories.into_boxed_slice().into(),
|
async_data_factories: self.data_factories.into_boxed_slice().into(),
|
||||||
endpoint: self.endpoint,
|
endpoint: self.endpoint,
|
||||||
services: Rc::new(RefCell::new(self.services)),
|
services: Rc::new(RefCell::new(self.services)),
|
||||||
|
@ -10,7 +10,7 @@ use futures_core::future::LocalBoxFuture;
|
|||||||
use futures_util::future::join_all;
|
use futures_util::future::join_all;
|
||||||
|
|
||||||
use crate::config::{AppConfig, AppService};
|
use crate::config::{AppConfig, AppService};
|
||||||
use crate::data::{DataFactory, FnDataFactory};
|
use crate::data::FnDataFactory;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::guard::Guard;
|
use crate::guard::Guard;
|
||||||
use crate::request::{HttpRequest, HttpRequestPool};
|
use crate::request::{HttpRequest, HttpRequestPool};
|
||||||
@ -35,7 +35,6 @@ where
|
|||||||
{
|
{
|
||||||
pub(crate) endpoint: T,
|
pub(crate) endpoint: T,
|
||||||
pub(crate) extensions: RefCell<Option<Extensions>>,
|
pub(crate) extensions: RefCell<Option<Extensions>>,
|
||||||
pub(crate) data_factories: Rc<[Box<dyn DataFactory>]>,
|
|
||||||
pub(crate) async_data_factories: Rc<[FnDataFactory]>,
|
pub(crate) async_data_factories: Rc<[FnDataFactory]>,
|
||||||
pub(crate) services: Rc<RefCell<Vec<Box<dyn AppServiceFactory>>>>,
|
pub(crate) services: Rc<RefCell<Vec<Box<dyn AppServiceFactory>>>>,
|
||||||
pub(crate) default: Option<Rc<HttpNewService>>,
|
pub(crate) default: Option<Rc<HttpNewService>>,
|
||||||
@ -71,8 +70,7 @@ where
|
|||||||
});
|
});
|
||||||
|
|
||||||
// App config
|
// App config
|
||||||
let mut config =
|
let mut config = AppService::new(config, default.clone());
|
||||||
AppService::new(config, default.clone(), self.data_factories.clone());
|
|
||||||
|
|
||||||
// register services
|
// register services
|
||||||
std::mem::take(&mut *self.services.borrow_mut())
|
std::mem::take(&mut *self.services.borrow_mut())
|
||||||
@ -119,8 +117,6 @@ where
|
|||||||
.take()
|
.take()
|
||||||
.unwrap_or_else(Extensions::new);
|
.unwrap_or_else(Extensions::new);
|
||||||
|
|
||||||
let data_factories = self.data_factories.clone();
|
|
||||||
|
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
// async data factories
|
// async data factories
|
||||||
let async_data_factories = factory_futs
|
let async_data_factories = factory_futs
|
||||||
@ -133,12 +129,9 @@ where
|
|||||||
let service = endpoint_fut.await?;
|
let service = endpoint_fut.await?;
|
||||||
|
|
||||||
// populate app data container from (async) data factories.
|
// populate app data container from (async) data factories.
|
||||||
data_factories
|
async_data_factories.iter().for_each(|factory| {
|
||||||
.iter()
|
factory.create(&mut app_data);
|
||||||
.chain(&async_data_factories)
|
});
|
||||||
.for_each(|factory| {
|
|
||||||
factory.create(&mut app_data);
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(AppInitService {
|
Ok(AppInitService {
|
||||||
service,
|
service,
|
||||||
|
@ -5,7 +5,7 @@ use actix_http::Extensions;
|
|||||||
use actix_router::ResourceDef;
|
use actix_router::ResourceDef;
|
||||||
use actix_service::{boxed, IntoServiceFactory, ServiceFactory};
|
use actix_service::{boxed, IntoServiceFactory, ServiceFactory};
|
||||||
|
|
||||||
use crate::data::{Data, DataFactory};
|
use crate::data::Data;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::guard::Guard;
|
use crate::guard::Guard;
|
||||||
use crate::resource::Resource;
|
use crate::resource::Resource;
|
||||||
@ -31,20 +31,14 @@ pub struct AppService {
|
|||||||
Option<Guards>,
|
Option<Guards>,
|
||||||
Option<Rc<ResourceMap>>,
|
Option<Rc<ResourceMap>>,
|
||||||
)>,
|
)>,
|
||||||
service_data: Rc<[Box<dyn DataFactory>]>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppService {
|
impl AppService {
|
||||||
/// Crate server settings instance
|
/// Crate server settings instance.
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(config: AppConfig, default: Rc<HttpNewService>) -> Self {
|
||||||
config: AppConfig,
|
|
||||||
default: Rc<HttpNewService>,
|
|
||||||
service_data: Rc<[Box<dyn DataFactory>]>,
|
|
||||||
) -> Self {
|
|
||||||
AppService {
|
AppService {
|
||||||
config,
|
config,
|
||||||
default,
|
default,
|
||||||
service_data,
|
|
||||||
root: true,
|
root: true,
|
||||||
services: Vec::new(),
|
services: Vec::new(),
|
||||||
}
|
}
|
||||||
@ -75,7 +69,6 @@ impl AppService {
|
|||||||
default: self.default.clone(),
|
default: self.default.clone(),
|
||||||
services: Vec::new(),
|
services: Vec::new(),
|
||||||
root: false,
|
root: false,
|
||||||
service_data: self.service_data.clone(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,15 +82,7 @@ impl AppService {
|
|||||||
self.default.clone()
|
self.default.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set global route data
|
/// Register HTTP service.
|
||||||
pub fn set_service_data(&self, extensions: &mut Extensions) -> bool {
|
|
||||||
for f in self.service_data.iter() {
|
|
||||||
f.create(extensions);
|
|
||||||
}
|
|
||||||
!self.service_data.is_empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Register http service
|
|
||||||
pub fn register_service<F, S>(
|
pub fn register_service<F, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
rdef: ResourceDef,
|
rdef: ResourceDef,
|
||||||
@ -168,47 +153,60 @@ impl Default for AppConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Service config is used for external configuration.
|
/// Enables parts of app configuration to be declared separately from the app itself. Helpful for
|
||||||
/// Part of application configuration could be offloaded
|
/// modularizing large applications.
|
||||||
/// to set of external methods. This could help with
|
///
|
||||||
/// modularization of big application configuration.
|
/// Merge a `ServiceConfig` into an app using [`App::configure`](crate::App::configure). Scope and
|
||||||
|
/// resources services have similar methods.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use actix_web::{web, App, HttpResponse};
|
||||||
|
///
|
||||||
|
/// // this function could be located in different module
|
||||||
|
/// fn config(cfg: &mut web::ServiceConfig) {
|
||||||
|
/// cfg.service(web::resource("/test")
|
||||||
|
/// .route(web::get().to(|| HttpResponse::Ok()))
|
||||||
|
/// .route(web::head().to(|| HttpResponse::MethodNotAllowed()))
|
||||||
|
/// );
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // merge `/test` routes from config function to App
|
||||||
|
/// App::new().configure(config);
|
||||||
|
/// ```
|
||||||
pub struct ServiceConfig {
|
pub struct ServiceConfig {
|
||||||
pub(crate) services: Vec<Box<dyn AppServiceFactory>>,
|
pub(crate) services: Vec<Box<dyn AppServiceFactory>>,
|
||||||
pub(crate) data: Vec<Box<dyn DataFactory>>,
|
|
||||||
pub(crate) external: Vec<ResourceDef>,
|
pub(crate) external: Vec<ResourceDef>,
|
||||||
pub(crate) extensions: Extensions,
|
pub(crate) app_data: Extensions,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceConfig {
|
impl ServiceConfig {
|
||||||
pub(crate) fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
services: Vec::new(),
|
services: Vec::new(),
|
||||||
data: Vec::new(),
|
|
||||||
external: Vec::new(),
|
external: Vec::new(),
|
||||||
extensions: Extensions::new(),
|
app_data: Extensions::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set application data. Application data could be accessed
|
/// Add shared app data item.
|
||||||
/// by using `Data<T>` extractor where `T` is data type.
|
|
||||||
///
|
///
|
||||||
/// This is same as `App::data()` method.
|
/// Counterpart to [`App::data()`](crate::App::data).
|
||||||
pub fn data<S: 'static>(&mut self, data: S) -> &mut Self {
|
pub fn data<U: 'static>(&mut self, data: U) -> &mut Self {
|
||||||
self.data.push(Box::new(Data::new(data)));
|
self.app_data(Data::new(data));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set arbitrary data item.
|
/// Add arbitrary app data item.
|
||||||
///
|
///
|
||||||
/// This is same as `App::data()` method.
|
/// Counterpart to [`App::app_data()`](crate::App::app_data).
|
||||||
pub fn app_data<U: 'static>(&mut self, ext: U) -> &mut Self {
|
pub fn app_data<U: 'static>(&mut self, ext: U) -> &mut Self {
|
||||||
self.extensions.insert(ext);
|
self.app_data.insert(ext);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configure route for a specific path.
|
/// Configure route for a specific path.
|
||||||
///
|
///
|
||||||
/// This is same as `App::route()` method.
|
/// Counterpart to [`App::route()`](crate::App::route).
|
||||||
pub fn route(&mut self, path: &str, mut route: Route) -> &mut Self {
|
pub fn route(&mut self, path: &str, mut route: Route) -> &mut Self {
|
||||||
self.service(
|
self.service(
|
||||||
Resource::new(path)
|
Resource::new(path)
|
||||||
@ -217,9 +215,9 @@ impl ServiceConfig {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register http service.
|
/// Register HTTP service factory.
|
||||||
///
|
///
|
||||||
/// This is same as `App::service()` method.
|
/// Counterpart to [`App::service()`](crate::App::service).
|
||||||
pub fn service<F>(&mut self, factory: F) -> &mut Self
|
pub fn service<F>(&mut self, factory: F) -> &mut Self
|
||||||
where
|
where
|
||||||
F: HttpServiceFactory + 'static,
|
F: HttpServiceFactory + 'static,
|
||||||
@ -231,11 +229,11 @@ impl ServiceConfig {
|
|||||||
|
|
||||||
/// Register an external resource.
|
/// Register an external resource.
|
||||||
///
|
///
|
||||||
/// External resources are useful for URL generation purposes only
|
/// External resources are useful for URL generation purposes only and are never considered for
|
||||||
/// and are never considered for matching at request time. Calls to
|
/// matching at request time. Calls to [`HttpRequest::url_for()`](crate::HttpRequest::url_for)
|
||||||
/// `HttpRequest::url_for()` will work as expected.
|
/// will work as expected.
|
||||||
///
|
///
|
||||||
/// This is same as `App::external_service()` method.
|
/// Counterpart to [`App::external_resource()`](crate::App::external_resource).
|
||||||
pub fn external_resource<N, U>(&mut self, name: N, url: U) -> &mut Self
|
pub fn external_resource<N, U>(&mut self, name: N, url: U) -> &mut Self
|
||||||
where
|
where
|
||||||
N: AsRef<str>,
|
N: AsRef<str>,
|
||||||
|
29
src/data.rs
29
src/data.rs
@ -10,8 +10,9 @@ use crate::dev::Payload;
|
|||||||
use crate::extract::FromRequest;
|
use crate::extract::FromRequest;
|
||||||
use crate::request::HttpRequest;
|
use crate::request::HttpRequest;
|
||||||
|
|
||||||
/// Application data factory
|
/// Data factory.
|
||||||
pub(crate) trait DataFactory {
|
pub(crate) trait DataFactory {
|
||||||
|
/// Return true if modifications were made to extensions map.
|
||||||
fn create(&self, extensions: &mut Extensions) -> bool;
|
fn create(&self, extensions: &mut Extensions) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,12 +127,8 @@ impl<T: ?Sized + 'static> FromRequest for Data<T> {
|
|||||||
|
|
||||||
impl<T: ?Sized + 'static> DataFactory for Data<T> {
|
impl<T: ?Sized + 'static> DataFactory for Data<T> {
|
||||||
fn create(&self, extensions: &mut Extensions) -> bool {
|
fn create(&self, extensions: &mut Extensions) -> bool {
|
||||||
if !extensions.contains::<Data<T>>() {
|
extensions.insert(Data(self.0.clone()));
|
||||||
extensions.insert(Data(self.0.clone()));
|
true
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +164,24 @@ mod tests {
|
|||||||
let req = TestRequest::default().to_request();
|
let req = TestRequest::default().to_request();
|
||||||
let resp = srv.call(req).await.unwrap();
|
let resp = srv.call(req).await.unwrap();
|
||||||
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
|
||||||
|
let mut srv = init_service(
|
||||||
|
App::new()
|
||||||
|
.data(10u32)
|
||||||
|
.data(13u32)
|
||||||
|
.app_data(12u64)
|
||||||
|
.app_data(15u64)
|
||||||
|
.default_service(web::to(|n: web::Data<u32>, req: HttpRequest| {
|
||||||
|
// in each case, the latter insertion should be preserved
|
||||||
|
assert_eq!(*req.app_data::<u64>().unwrap(), 15);
|
||||||
|
assert_eq!(*n.into_inner(), 13);
|
||||||
|
HttpResponse::Ok()
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let req = TestRequest::default().to_request();
|
||||||
|
let resp = srv.call(req).await.unwrap();
|
||||||
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
|
@ -203,10 +203,10 @@ where
|
|||||||
///
|
///
|
||||||
/// Data of different types from parent contexts will still be accessible.
|
/// Data of different types from parent contexts will still be accessible.
|
||||||
pub fn app_data<U: 'static>(mut self, data: U) -> Self {
|
pub fn app_data<U: 'static>(mut self, data: U) -> Self {
|
||||||
if self.app_data.is_none() {
|
self.app_data
|
||||||
self.app_data = Some(Extensions::new());
|
.get_or_insert_with(Extensions::new)
|
||||||
}
|
.insert(data);
|
||||||
self.app_data.as_mut().unwrap().insert(data);
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,18 +382,16 @@ where
|
|||||||
} else {
|
} else {
|
||||||
Some(std::mem::take(&mut self.guards))
|
Some(std::mem::take(&mut self.guards))
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut rdef = if config.is_root() || !self.rdef.is_empty() {
|
let mut rdef = if config.is_root() || !self.rdef.is_empty() {
|
||||||
ResourceDef::new(insert_slash(self.rdef.clone()))
|
ResourceDef::new(insert_slash(self.rdef.clone()))
|
||||||
} else {
|
} else {
|
||||||
ResourceDef::new(self.rdef.clone())
|
ResourceDef::new(self.rdef.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(ref name) = self.name {
|
if let Some(ref name) = self.name {
|
||||||
*rdef.name_mut() = name.clone();
|
*rdef.name_mut() = name.clone();
|
||||||
}
|
}
|
||||||
// custom app data storage
|
|
||||||
if let Some(ref mut ext) = self.app_data {
|
|
||||||
config.set_service_data(ext);
|
|
||||||
}
|
|
||||||
|
|
||||||
config.register_service(rdef, guards, self, None)
|
config.register_service(rdef, guards, self, None)
|
||||||
}
|
}
|
||||||
@ -479,12 +477,15 @@ impl Service<ServiceRequest> for ResourceService {
|
|||||||
if let Some(ref app_data) = self.app_data {
|
if let Some(ref app_data) = self.app_data {
|
||||||
req.add_data_container(app_data.clone());
|
req.add_data_container(app_data.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
return route.call(req);
|
return route.call(req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref app_data) = self.app_data {
|
if let Some(ref app_data) = self.app_data {
|
||||||
req.add_data_container(app_data.clone());
|
req.add_data_container(app_data.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.default.call(req)
|
self.default.call(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
src/scope.rs
24
src/scope.rs
@ -155,10 +155,10 @@ where
|
|||||||
///
|
///
|
||||||
/// Data of different types from parent contexts will still be accessible.
|
/// Data of different types from parent contexts will still be accessible.
|
||||||
pub fn app_data<U: 'static>(mut self, data: U) -> Self {
|
pub fn app_data<U: 'static>(mut self, data: U) -> Self {
|
||||||
if self.app_data.is_none() {
|
self.app_data
|
||||||
self.app_data = Some(Extensions::new());
|
.get_or_insert_with(Extensions::new)
|
||||||
}
|
.insert(data);
|
||||||
self.app_data.as_mut().unwrap().insert(data);
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,18 +200,9 @@ where
|
|||||||
self.services.extend(cfg.services);
|
self.services.extend(cfg.services);
|
||||||
self.external.extend(cfg.external);
|
self.external.extend(cfg.external);
|
||||||
|
|
||||||
if !cfg.data.is_empty() {
|
|
||||||
let mut data = self.app_data.unwrap_or_else(Extensions::new);
|
|
||||||
|
|
||||||
for value in cfg.data.iter() {
|
|
||||||
value.create(&mut data);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.app_data = Some(data);
|
|
||||||
}
|
|
||||||
self.app_data
|
self.app_data
|
||||||
.get_or_insert_with(Extensions::new)
|
.get_or_insert_with(Extensions::new)
|
||||||
.extend(cfg.extensions);
|
.extend(cfg.app_data);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,11 +423,6 @@ where
|
|||||||
rmap.add(&mut rdef, None);
|
rmap.add(&mut rdef, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
// custom app data storage
|
|
||||||
if let Some(ref mut ext) = self.app_data {
|
|
||||||
config.set_service_data(ext);
|
|
||||||
}
|
|
||||||
|
|
||||||
// complete scope pipeline creation
|
// complete scope pipeline creation
|
||||||
*self.factory_ref.borrow_mut() = Some(ScopeFactory {
|
*self.factory_ref.borrow_mut() = Some(ScopeFactory {
|
||||||
app_data: self.app_data.take().map(Rc::new),
|
app_data: self.app_data.take().map(Rc::new),
|
||||||
|
@ -231,8 +231,10 @@ impl ServiceRequest {
|
|||||||
self.payload = payload;
|
self.payload = payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
/// Add data container to request's resolution set.
|
||||||
/// Add app data container to request's resolution set.
|
///
|
||||||
|
/// In middleware, prefer [`extensions_mut`](ServiceRequest::extensions_mut) for request-local
|
||||||
|
/// data since it is assumed that the same app data is presented for every request.
|
||||||
pub fn add_data_container(&mut self, extensions: Rc<Extensions>) {
|
pub fn add_data_container(&mut self, extensions: Rc<Extensions>) {
|
||||||
Rc::get_mut(&mut (self.req).inner)
|
Rc::get_mut(&mut (self.req).inner)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
Loading…
Reference in New Issue
Block a user