@@ -49,9 +49,9 @@ impl App {
4949 ///# fn get_user() -> User { unimplemented!() }
5050 ///# fn create_user(user: Json<User>) -> i32 { unimplemented!() }
5151 /// ```
52- pub fn group < ' a , F > ( & ' a mut self , prefix : & ' a str , f : F )
53- where
54- F : FnOnce ( & mut RouteGroup < ' a > )
52+ pub fn group < F > ( & mut self , prefix : & str , f : F )
53+ where
54+ F : FnOnce ( & mut RouteGroup < ' _ > )
5555 {
5656 let mut group = RouteGroup :: new ( self , prefix) ;
5757
@@ -62,15 +62,15 @@ impl App {
6262 }
6363
6464 /// Adds a request handler that matches HTTP GET requests for the specified pattern.
65- ///
65+ ///
6666 /// # Examples
6767 /// ```no_run
6868 /// use volga::{App, ok};
6969 ///
7070 ///# #[tokio::main]
7171 ///# async fn main() -> std::io::Result<()> {
7272 /// let mut app = App::new();
73- ///
73+ ///
7474 /// app.map_get("/hello", || async {
7575 /// ok!("Hello World!")
7676 /// });
@@ -380,7 +380,7 @@ pub struct Route<'a> {
380380/// Represents a group of routes
381381pub struct RouteGroup < ' a > {
382382 pub ( crate ) app : & ' a mut App ,
383- pub ( crate ) prefix : & ' a str ,
383+ pub ( crate ) prefix : String ,
384384 pub ( crate ) route_count : usize ,
385385 #[ cfg( feature = "middleware" ) ]
386386 pub ( crate ) middleware : Vec < MiddlewareFn > ,
@@ -452,13 +452,66 @@ impl<'a> RouteGroup<'a> {
452452 }
453453}
454454
455+ impl < ' a > RouteGroup < ' a > {
456+ /// Maps a sub-group of request handlers combined by `sub_prefix`.
457+ ///
458+ /// Inherits the parent group's middleware, CORS policy, and OpenAPI
459+ /// configuration. Any middleware or settings added to the sub-group
460+ /// apply only to routes within it (and any further nested groups),
461+ /// running after the parent's middleware.
462+ ///
463+ /// # Examples
464+ /// ```no_run
465+ /// use volga::{App, ok};
466+ ///
467+ ///# #[tokio::main]
468+ ///# async fn main() -> std::io::Result<()> {
469+ /// let mut app = App::new();
470+ ///
471+ /// app.group("/api", |api| {
472+ /// api.map_get("/info", || async { ok!() });
473+ ///
474+ /// api.group("/users", |users| {
475+ /// users.map_get("/{id}", |id: i32| async move { ok!(id) });
476+ /// });
477+ /// });
478+ ///# app.run().await
479+ ///# }
480+ /// ```
481+ pub fn group < F > ( & mut self , sub_prefix : & str , f : F )
482+ where
483+ F : FnOnce ( & mut RouteGroup < ' _ > )
484+ {
485+ let full_prefix = [ self . prefix . as_str ( ) , sub_prefix] . concat ( ) ;
486+ let mut child = RouteGroup {
487+ app : self . app ,
488+ prefix : full_prefix,
489+ route_count : 0 ,
490+ #[ cfg( feature = "middleware" ) ]
491+ middleware : self . middleware . clone ( ) ,
492+ #[ cfg( feature = "middleware" ) ]
493+ cors : self . cors . clone ( ) ,
494+ #[ cfg( feature = "openapi" ) ]
495+ openapi_config : self . openapi_config . clone ( ) ,
496+ } ;
497+
498+ #[ cfg( feature = "openapi" ) ]
499+ {
500+ let tag = child. prefix . clone ( ) ;
501+ child. open_api ( |cfg| cfg. with_tag ( tag) ) ;
502+ }
503+
504+ f ( & mut child) ;
505+ }
506+ }
507+
455508macro_rules! define_route_group_methods {
456509 ( $( ( $fn_name: ident, $http_method: expr) ) * ) => {
457510 impl <' a> RouteGroup <' a> {
458- fn new( app: & ' a mut App , prefix: & ' a str ) -> Self {
511+ fn new( app: & ' a mut App , prefix: & str ) -> Self {
459512 RouteGroup {
460513 app,
461- prefix,
514+ prefix: prefix . to_string ( ) ,
462515 route_count: 0 ,
463516 #[ cfg( feature = "middleware" ) ]
464517 middleware: Vec :: with_capacity( 4 ) ,
@@ -478,7 +531,7 @@ macro_rules! define_route_group_methods {
478531 Args : FromRequest + Send + ' static ,
479532 {
480533 self . route_count += 1 ;
481- let pattern = [ self . prefix, pattern] . concat( ) ;
534+ let pattern = [ self . prefix. as_str ( ) , pattern] . concat( ) ;
482535
483536 #[ cfg( feature = "middleware" ) ]
484537 {
0 commit comments