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

Scope configuration (#880)

* WIP: Scope configuarion

* Extensions: Fix into_iter()

* Scope: Fix tests

* Add ScopeConfig to web

Committing from mobile, if this doesn't look good it's because I haven't tested it...

* Scope Config: Use ServiceConfig instead

* Scope: Switch to ServiceConfig in doc

* ScopeConfig: Remove unnecessary changes, handle the case when data is empty

* ScopeConfig: Remove changes from actix-http
This commit is contained in:
Denys Vitali 2019-06-03 19:12:37 +02:00 committed by Nikolay Kim
parent 4a179d1ae1
commit 1fce4876f3
2 changed files with 88 additions and 1 deletions

View File

@ -188,7 +188,7 @@ impl ServiceConfig {
} }
} }
/// Set application data. Applicatin data could be accessed /// Set application data. Application data could be accessed
/// by using `Data<T>` extractor where `T` is data type. /// by using `Data<T>` extractor where `T` is data type.
/// ///
/// This is same as `App::data()` method. /// This is same as `App::data()` method.

View File

@ -21,6 +21,7 @@ use crate::route::Route;
use crate::service::{ use crate::service::{
ServiceFactory, ServiceFactoryWrapper, ServiceRequest, ServiceResponse, ServiceFactory, ServiceFactoryWrapper, ServiceRequest, ServiceResponse,
}; };
use crate::config::ServiceConfig;
type Guards = Vec<Box<Guard>>; type Guards = Vec<Box<Guard>>;
type HttpService = BoxedService<ServiceRequest, ServiceResponse, Error>; type HttpService = BoxedService<ServiceRequest, ServiceResponse, Error>;
@ -83,6 +84,56 @@ impl Scope {
factory_ref: fref, factory_ref: fref,
} }
} }
/// Run external configuration as part of the scope building
/// process
///
/// This function is useful for moving parts of configuration to a
/// different module or even library. For example,
/// some of the resource's configuration could be moved to different module.
///
/// ```rust
/// # extern crate actix_web;
/// use actix_web::{web, middleware, 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()))
/// );
/// }
///
/// fn main() {
/// let app = App::new()
/// .wrap(middleware::Logger::default())
/// .service(
/// web::scope("/api")
/// .configure(config)
/// )
/// .route("/index.html", web::get().to(|| HttpResponse::Ok()));
/// }
/// ```
pub fn configure<F>(mut self, f: F) -> Self
where
F: FnOnce(&mut ServiceConfig),
{
let mut cfg = ServiceConfig::new();
f(&mut cfg);
self.services.extend(cfg.services);
if !cfg.data.is_empty() {
let mut data = self.data.unwrap_or(Extensions::new());
for value in cfg.data.iter() {
value.create(&mut data);
}
self.data = Some(data);
}
self
}
} }
impl<T> Scope<T> impl<T> Scope<T>
@ -1022,4 +1073,40 @@ mod tests {
let resp = call_service(&mut srv, req); let resp = call_service(&mut srv, req);
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
} }
#[test]
fn test_scope_config() {
let mut srv = init_service(
App::new().service(
web::scope("/app")
.configure(|s|{
s.route("/path1", web::get().to(||HttpResponse::Ok()));
})
),
);
let req = TestRequest::with_uri("/app/path1").to_request();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
}
#[test]
fn test_scope_config_2() {
let mut srv = init_service(
App::new().service(
web::scope("/app")
.configure(|s|{
s.service(
web::scope("/v1")
.configure(|s|{
s.route("/", web::get().to(||HttpResponse::Ok()));
}));
})
),
);
let req = TestRequest::with_uri("/app/v1/").to_request();
let resp = block_on(srv.call(req)).unwrap();
assert_eq!(resp.status(), StatusCode::OK);
}
} }