mirror of
https://github.com/fafhrd91/actix-web
synced 2025-02-22 04:03:17 +01:00
add services register for tuple and vec of services (#1933)
This commit is contained in:
parent
266cf0622c
commit
dddb623a11
@ -4,6 +4,8 @@
|
|||||||
### Added
|
### Added
|
||||||
* The method `Either<web::Json<T>, web::Form<T>>::into_inner()` which returns the inner type for
|
* The method `Either<web::Json<T>, web::Form<T>>::into_inner()` which returns the inner type for
|
||||||
whichever variant was created. Also works for `Either<web::Form<T>, web::Json<T>>`. [#1894]
|
whichever variant was created. Also works for `Either<web::Form<T>, web::Json<T>>`. [#1894]
|
||||||
|
* Add `services!` macro for helping register multiple services to `App`. [#1933]
|
||||||
|
* Enable registering vector of same type of `HttpServiceFactory` to `App` [#1933]
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
* Rework `Responder` trait to be sync and returns `Response`/`HttpResponse` directly.
|
* Rework `Responder` trait to be sync and returns `Response`/`HttpResponse` directly.
|
||||||
@ -34,6 +36,7 @@
|
|||||||
[#1869]: https://github.com/actix/actix-web/pull/1869
|
[#1869]: https://github.com/actix/actix-web/pull/1869
|
||||||
[#1905]: https://github.com/actix/actix-web/pull/1905
|
[#1905]: https://github.com/actix/actix-web/pull/1905
|
||||||
[#1906]: https://github.com/actix/actix-web/pull/1906
|
[#1906]: https://github.com/actix/actix-web/pull/1906
|
||||||
|
[#1933]: https://github.com/actix/actix-web/pull/1933
|
||||||
[#1957]: https://github.com/actix/actix-web/pull/1957
|
[#1957]: https://github.com/actix/actix-web/pull/1957
|
||||||
|
|
||||||
|
|
||||||
|
142
src/service.rs
142
src/service.rs
@ -22,6 +22,13 @@ pub trait HttpServiceFactory {
|
|||||||
fn register(self, config: &mut AppService);
|
fn register(self, config: &mut AppService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: HttpServiceFactory> HttpServiceFactory for Vec<T> {
|
||||||
|
fn register(self, config: &mut AppService) {
|
||||||
|
self.into_iter()
|
||||||
|
.for_each(|factory| factory.register(config));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) trait AppServiceFactory {
|
pub(crate) trait AppServiceFactory {
|
||||||
fn register(&mut self, config: &mut AppService);
|
fn register(&mut self, config: &mut AppService);
|
||||||
}
|
}
|
||||||
@ -532,6 +539,65 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Macro helping register different types of services at the sametime.
|
||||||
|
///
|
||||||
|
/// The service type must be implementing [`HttpServiceFactory`](self::HttpServiceFactory) trait.
|
||||||
|
///
|
||||||
|
/// The max number of services can be grouped together is 12.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use actix_web::{services, web, App};
|
||||||
|
///
|
||||||
|
/// let services = services![
|
||||||
|
/// web::resource("/test2").to(|| async { "test2" }),
|
||||||
|
/// web::scope("/test3").route("/", web::get().to(|| async { "test3" }))
|
||||||
|
/// ];
|
||||||
|
///
|
||||||
|
/// let app = App::new().service(services);
|
||||||
|
///
|
||||||
|
/// // services macro just convert multiple services to a tuple.
|
||||||
|
/// // below would also work without importing the macro.
|
||||||
|
/// let app = App::new().service((
|
||||||
|
/// web::resource("/test2").to(|| async { "test2" }),
|
||||||
|
/// web::scope("/test3").route("/", web::get().to(|| async { "test3" }))
|
||||||
|
/// ));
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! services {
|
||||||
|
($($x:expr),+ $(,)?) => {
|
||||||
|
($($x,)+)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// HttpServiceFactory trait impl for tuples
|
||||||
|
macro_rules! service_tuple ({ $(($n:tt, $T:ident)),+} => {
|
||||||
|
impl<$($T: HttpServiceFactory),+> HttpServiceFactory for ($($T,)+) {
|
||||||
|
fn register(self, config: &mut AppService) {
|
||||||
|
$(self.$n.register(config);)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
mod m {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
service_tuple!((0, A));
|
||||||
|
service_tuple!((0, A), (1, B));
|
||||||
|
service_tuple!((0, A), (1, B), (2, C));
|
||||||
|
service_tuple!((0, A), (1, B), (2, C), (3, D));
|
||||||
|
service_tuple!((0, A), (1, B), (2, C), (3, D), (4, E));
|
||||||
|
service_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
|
||||||
|
service_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
|
||||||
|
service_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H));
|
||||||
|
service_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I));
|
||||||
|
service_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J));
|
||||||
|
service_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J), (10, K));
|
||||||
|
service_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J), (10, K), (11, L));
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -606,4 +672,80 @@ mod tests {
|
|||||||
assert!(s.contains("ServiceResponse"));
|
assert!(s.contains("ServiceResponse"));
|
||||||
assert!(s.contains("x-test"));
|
assert!(s.contains("x-test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_services_macro() {
|
||||||
|
let scoped = services![
|
||||||
|
web::service("/scoped_test1").name("scoped_test1").finish(
|
||||||
|
|req: ServiceRequest| async {
|
||||||
|
Ok(req.into_response(HttpResponse::Ok().finish()))
|
||||||
|
}
|
||||||
|
),
|
||||||
|
web::resource("/scoped_test2").to(|| async { "test2" }),
|
||||||
|
];
|
||||||
|
|
||||||
|
let services = services![
|
||||||
|
web::service("/test1")
|
||||||
|
.name("test")
|
||||||
|
.finish(|req: ServiceRequest| async {
|
||||||
|
Ok(req.into_response(HttpResponse::Ok().finish()))
|
||||||
|
}),
|
||||||
|
web::resource("/test2").to(|| async { "test2" }),
|
||||||
|
web::scope("/test3").service(scoped)
|
||||||
|
];
|
||||||
|
|
||||||
|
let srv = init_service(App::new().service(services)).await;
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/test1").to_request();
|
||||||
|
let resp = srv.call(req).await.unwrap();
|
||||||
|
assert_eq!(resp.status(), http::StatusCode::OK);
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/test2").to_request();
|
||||||
|
let resp = srv.call(req).await.unwrap();
|
||||||
|
assert_eq!(resp.status(), http::StatusCode::OK);
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/test3/scoped_test1").to_request();
|
||||||
|
let resp = srv.call(req).await.unwrap();
|
||||||
|
assert_eq!(resp.status(), http::StatusCode::OK);
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/test3/scoped_test2").to_request();
|
||||||
|
let resp = srv.call(req).await.unwrap();
|
||||||
|
assert_eq!(resp.status(), http::StatusCode::OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_services_vec() {
|
||||||
|
let services = vec![
|
||||||
|
web::resource("/test1").to(|| async { "test1" }),
|
||||||
|
web::resource("/test2").to(|| async { "test2" }),
|
||||||
|
];
|
||||||
|
|
||||||
|
let scoped = vec![
|
||||||
|
web::resource("/scoped_test1").to(|| async { "test1" }),
|
||||||
|
web::resource("/scoped_test2").to(|| async { "test2" }),
|
||||||
|
];
|
||||||
|
|
||||||
|
let srv = init_service(
|
||||||
|
App::new()
|
||||||
|
.service(services)
|
||||||
|
.service(web::scope("/test3").service(scoped)),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/test1").to_request();
|
||||||
|
let resp = srv.call(req).await.unwrap();
|
||||||
|
assert_eq!(resp.status(), http::StatusCode::OK);
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/test2").to_request();
|
||||||
|
let resp = srv.call(req).await.unwrap();
|
||||||
|
assert_eq!(resp.status(), http::StatusCode::OK);
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/test3/scoped_test1").to_request();
|
||||||
|
let resp = srv.call(req).await.unwrap();
|
||||||
|
assert_eq!(resp.status(), http::StatusCode::OK);
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/test3/scoped_test2").to_request();
|
||||||
|
let resp = srv.call(req).await.unwrap();
|
||||||
|
assert_eq!(resp.status(), http::StatusCode::OK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user