diff --git a/app.go b/app.go index f725424e..fcad05bf 100644 --- a/app.go +++ b/app.go @@ -9,6 +9,8 @@ package fiber import ( "bufio" + "encoding/json" + "encoding/xml" "errors" "fmt" "net" @@ -20,9 +22,6 @@ import ( "sync" "time" - "encoding/json" - "encoding/xml" - "github.com/gofiber/fiber/v2/utils" "github.com/valyala/fasthttp" ) @@ -109,7 +108,6 @@ type App struct { hooks *Hooks // Latest route & group latestRoute *Route - latestGroup *Group // TLS handler tlsHandler *TLSHandler // Mount fields @@ -485,7 +483,6 @@ func New(config ...Config) *App { getBytes: utils.UnsafeBytes, getString: utils.UnsafeString, latestRoute: &Route{}, - latestGroup: &Group{}, } // Define hooks @@ -583,8 +580,10 @@ func (app *App) SetTLSHandler(tlsHandler *TLSHandler) { // Name Assign name to specific route. func (app *App) Name(name string) Router { app.mutex.Lock() - if strings.HasPrefix(app.latestRoute.path, app.latestGroup.Prefix) { - app.latestRoute.Name = app.latestGroup.name + name + + latestGroup := app.latestRoute.group + if latestGroup != nil { + app.latestRoute.Name = latestGroup.name + name } else { app.latestRoute.Name = name } @@ -656,7 +655,7 @@ func (app *App) Use(args ...interface{}) Router { panic(fmt.Sprintf("use: invalid handler %v\n", reflect.TypeOf(arg))) } } - app.register(methodUse, prefix, handlers...) + app.register(methodUse, prefix, nil, handlers...) return app } @@ -715,7 +714,7 @@ func (app *App) Patch(path string, handlers ...Handler) Router { // Add allows you to specify a HTTP method to register a route func (app *App) Add(method, path string, handlers ...Handler) Router { - return app.register(method, path, handlers...) + return app.register(method, path, nil, handlers...) } // Static will create a file server serving static files @@ -736,10 +735,10 @@ func (app *App) All(path string, handlers ...Handler) Router { // api := app.Group("/api") // api.Get("/users", handler) func (app *App) Group(prefix string, handlers ...Handler) Router { - if len(handlers) > 0 { - app.register(methodUse, prefix, handlers...) - } grp := &Group{Prefix: prefix, app: app} + if len(handlers) > 0 { + app.register(methodUse, prefix, grp, handlers...) + } if err := app.hooks.executeOnGroupHooks(*grp); err != nil { panic(err) } diff --git a/app_test.go b/app_test.go index 2bef6a47..2e87114b 100644 --- a/app_test.go +++ b/app_test.go @@ -587,15 +587,16 @@ func Test_App_Route_Naming(t *testing.T) { app.Name("doe") jane := app.Group("/jane").Name("jane.") + group := app.Group("/group") + subGroup := jane.Group("/sub-group").Name("sub.") + jane.Get("/test", handler).Name("test") jane.Trace("/trace", handler).Name("trace") - group := app.Group("/group") group.Get("/test", handler).Name("test") app.Post("/post", handler).Name("post") - subGroup := jane.Group("/sub-group").Name("sub.") subGroup.Get("/done", handler).Name("done") utils.AssertEqual(t, "post", app.GetRoute("post").Name) diff --git a/group.go b/group.go index a59eaed8..93826807 100644 --- a/group.go +++ b/group.go @@ -7,13 +7,13 @@ package fiber import ( "fmt" "reflect" - "strings" ) // Group struct type Group struct { - app *App - name string + app *App + parentGroup *Group + name string Prefix string } @@ -21,15 +21,14 @@ type Group struct { // Name Assign name to specific route. func (grp *Group) Name(name string) Router { grp.app.mutex.Lock() - if strings.HasPrefix(grp.Prefix, grp.app.latestGroup.Prefix) { - grp.name = grp.app.latestGroup.name + name + + if grp.parentGroup != nil { + grp.name = grp.parentGroup.name + name } else { grp.name = name } - grp.app.latestGroup = grp - - if err := grp.app.hooks.executeOnGroupNameHooks(*grp.app.latestGroup); err != nil { + if err := grp.app.hooks.executeOnGroupNameHooks(*grp); err != nil { panic(err) } grp.app.mutex.Unlock() @@ -64,15 +63,15 @@ func (grp *Group) Use(args ...interface{}) Router { panic(fmt.Sprintf("use: invalid handler %v\n", reflect.TypeOf(arg))) } } - grp.app.register(methodUse, getGroupPath(grp.Prefix, prefix), handlers...) + grp.app.register(methodUse, getGroupPath(grp.Prefix, prefix), grp, handlers...) return grp } // Get registers a route for GET methods that requests a representation // of the specified resource. Requests using GET should only retrieve data. func (grp *Group) Get(path string, handlers ...Handler) Router { - path = getGroupPath(grp.Prefix, path) - return grp.app.Add(MethodHead, path, handlers...).Add(MethodGet, path, handlers...) + grp.Add(MethodHead, path, handlers...) + return grp.Add(MethodGet, path, handlers...) } // Head registers a route for HEAD methods that asks for a response identical @@ -124,7 +123,7 @@ func (grp *Group) Patch(path string, handlers ...Handler) Router { // Add allows you to specify a HTTP method to register a route func (grp *Group) Add(method, path string, handlers ...Handler) Router { - return grp.app.register(method, getGroupPath(grp.Prefix, path), handlers...) + return grp.app.register(method, getGroupPath(grp.Prefix, path), grp, handlers...) } // Static will create a file server serving static files @@ -147,9 +146,17 @@ func (grp *Group) All(path string, handlers ...Handler) Router { func (grp *Group) Group(prefix string, handlers ...Handler) Router { prefix = getGroupPath(grp.Prefix, prefix) if len(handlers) > 0 { - _ = grp.app.register(methodUse, prefix, handlers...) + _ = grp.app.register(methodUse, prefix, grp, handlers...) } - return grp.app.Group(prefix) + + // Create new group + newGrp := &Group{Prefix: prefix, app: grp.app, parentGroup: grp} + if err := grp.app.hooks.executeOnGroupHooks(*newGrp); err != nil { + panic(err) + } + + return newGrp + } // Route is used to define routes with a common prefix inside the common function. diff --git a/router.go b/router.go index 642149d5..d83c1868 100644 --- a/router.go +++ b/router.go @@ -52,6 +52,7 @@ type Route struct { root bool // Path equals '/' path string // Prettified path routeParser routeParser // Parameter parser + group *Group // Group instance. used for routes in groups // Public fields Method string `json:"method"` // HTTP method @@ -211,7 +212,7 @@ func (app *App) copyRoute(route *Route) *Route { } } -func (app *App) register(method, pathRaw string, handlers ...Handler) Router { +func (app *App) register(method, pathRaw string, group *Group, handlers ...Handler) Router { // Uppercase HTTP methods method = utils.ToUpper(method) // Check if the HTTP method is valid unless it's USE @@ -262,6 +263,9 @@ func (app *App) register(method, pathRaw string, handlers ...Handler) Router { routeParser: parsedPretty, Params: parsedRaw.params, + // Group data + group: group, + // Public data Path: pathRaw, Method: method, diff --git a/router_test.go b/router_test.go index eceae1fd..fbd82e4b 100644 --- a/router_test.go +++ b/router_test.go @@ -280,7 +280,7 @@ func Test_Router_Register_Missing_Handler(t *testing.T) { utils.AssertEqual(t, "missing handler in route: /doe\n", fmt.Sprintf("%v", err)) } }() - app.register("USE", "/doe") + app.register("USE", "/doe", nil) } func Test_Ensure_Router_Interface_Implementation(t *testing.T) {