mirror of https://github.com/gofiber/fiber.git
🐛 bug: fix naming of routes inside groups (#2199)
* 🐛 bug: fix naming of routes inside groups
* fix tests
* bug: fix naming of routes inside groups
Co-authored-by: René Werner <rene@gofiber.io>
pull/2107/head
parent
13247206ab
commit
581af0052d
23
app.go
23
app.go
|
@ -9,6 +9,8 @@ package fiber
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"encoding/json"
|
||||||
|
"encoding/xml"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
@ -20,9 +22,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"encoding/json"
|
|
||||||
"encoding/xml"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2/utils"
|
"github.com/gofiber/fiber/v2/utils"
|
||||||
"github.com/valyala/fasthttp"
|
"github.com/valyala/fasthttp"
|
||||||
)
|
)
|
||||||
|
@ -109,7 +108,6 @@ type App struct {
|
||||||
hooks *Hooks
|
hooks *Hooks
|
||||||
// Latest route & group
|
// Latest route & group
|
||||||
latestRoute *Route
|
latestRoute *Route
|
||||||
latestGroup *Group
|
|
||||||
// TLS handler
|
// TLS handler
|
||||||
tlsHandler *TLSHandler
|
tlsHandler *TLSHandler
|
||||||
// Mount fields
|
// Mount fields
|
||||||
|
@ -485,7 +483,6 @@ func New(config ...Config) *App {
|
||||||
getBytes: utils.UnsafeBytes,
|
getBytes: utils.UnsafeBytes,
|
||||||
getString: utils.UnsafeString,
|
getString: utils.UnsafeString,
|
||||||
latestRoute: &Route{},
|
latestRoute: &Route{},
|
||||||
latestGroup: &Group{},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define hooks
|
// Define hooks
|
||||||
|
@ -583,8 +580,10 @@ func (app *App) SetTLSHandler(tlsHandler *TLSHandler) {
|
||||||
// Name Assign name to specific route.
|
// Name Assign name to specific route.
|
||||||
func (app *App) Name(name string) Router {
|
func (app *App) Name(name string) Router {
|
||||||
app.mutex.Lock()
|
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 {
|
} else {
|
||||||
app.latestRoute.Name = name
|
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)))
|
panic(fmt.Sprintf("use: invalid handler %v\n", reflect.TypeOf(arg)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app.register(methodUse, prefix, handlers...)
|
app.register(methodUse, prefix, nil, handlers...)
|
||||||
return app
|
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
|
// Add allows you to specify a HTTP method to register a route
|
||||||
func (app *App) Add(method, path string, handlers ...Handler) Router {
|
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
|
// 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 := app.Group("/api")
|
||||||
// api.Get("/users", handler)
|
// api.Get("/users", handler)
|
||||||
func (app *App) Group(prefix string, handlers ...Handler) Router {
|
func (app *App) Group(prefix string, handlers ...Handler) Router {
|
||||||
if len(handlers) > 0 {
|
|
||||||
app.register(methodUse, prefix, handlers...)
|
|
||||||
}
|
|
||||||
grp := &Group{Prefix: prefix, app: app}
|
grp := &Group{Prefix: prefix, app: app}
|
||||||
|
if len(handlers) > 0 {
|
||||||
|
app.register(methodUse, prefix, grp, handlers...)
|
||||||
|
}
|
||||||
if err := app.hooks.executeOnGroupHooks(*grp); err != nil {
|
if err := app.hooks.executeOnGroupHooks(*grp); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -587,15 +587,16 @@ func Test_App_Route_Naming(t *testing.T) {
|
||||||
app.Name("doe")
|
app.Name("doe")
|
||||||
|
|
||||||
jane := app.Group("/jane").Name("jane.")
|
jane := app.Group("/jane").Name("jane.")
|
||||||
|
group := app.Group("/group")
|
||||||
|
subGroup := jane.Group("/sub-group").Name("sub.")
|
||||||
|
|
||||||
jane.Get("/test", handler).Name("test")
|
jane.Get("/test", handler).Name("test")
|
||||||
jane.Trace("/trace", handler).Name("trace")
|
jane.Trace("/trace", handler).Name("trace")
|
||||||
|
|
||||||
group := app.Group("/group")
|
|
||||||
group.Get("/test", handler).Name("test")
|
group.Get("/test", handler).Name("test")
|
||||||
|
|
||||||
app.Post("/post", handler).Name("post")
|
app.Post("/post", handler).Name("post")
|
||||||
|
|
||||||
subGroup := jane.Group("/sub-group").Name("sub.")
|
|
||||||
subGroup.Get("/done", handler).Name("done")
|
subGroup.Get("/done", handler).Name("done")
|
||||||
|
|
||||||
utils.AssertEqual(t, "post", app.GetRoute("post").Name)
|
utils.AssertEqual(t, "post", app.GetRoute("post").Name)
|
||||||
|
|
31
group.go
31
group.go
|
@ -7,12 +7,12 @@ package fiber
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Group struct
|
// Group struct
|
||||||
type Group struct {
|
type Group struct {
|
||||||
app *App
|
app *App
|
||||||
|
parentGroup *Group
|
||||||
name string
|
name string
|
||||||
|
|
||||||
Prefix string
|
Prefix string
|
||||||
|
@ -21,15 +21,14 @@ type Group struct {
|
||||||
// Name Assign name to specific route.
|
// Name Assign name to specific route.
|
||||||
func (grp *Group) Name(name string) Router {
|
func (grp *Group) Name(name string) Router {
|
||||||
grp.app.mutex.Lock()
|
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 {
|
} else {
|
||||||
grp.name = name
|
grp.name = name
|
||||||
}
|
}
|
||||||
|
|
||||||
grp.app.latestGroup = grp
|
if err := grp.app.hooks.executeOnGroupNameHooks(*grp); err != nil {
|
||||||
|
|
||||||
if err := grp.app.hooks.executeOnGroupNameHooks(*grp.app.latestGroup); err != nil {
|
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
grp.app.mutex.Unlock()
|
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)))
|
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
|
return grp
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get registers a route for GET methods that requests a representation
|
// Get registers a route for GET methods that requests a representation
|
||||||
// of the specified resource. Requests using GET should only retrieve data.
|
// of the specified resource. Requests using GET should only retrieve data.
|
||||||
func (grp *Group) Get(path string, handlers ...Handler) Router {
|
func (grp *Group) Get(path string, handlers ...Handler) Router {
|
||||||
path = getGroupPath(grp.Prefix, path)
|
grp.Add(MethodHead, path, handlers...)
|
||||||
return grp.app.Add(MethodHead, path, handlers...).Add(MethodGet, path, handlers...)
|
return grp.Add(MethodGet, path, handlers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Head registers a route for HEAD methods that asks for a response identical
|
// 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
|
// Add allows you to specify a HTTP method to register a route
|
||||||
func (grp *Group) Add(method, path string, handlers ...Handler) Router {
|
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
|
// 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 {
|
func (grp *Group) Group(prefix string, handlers ...Handler) Router {
|
||||||
prefix = getGroupPath(grp.Prefix, prefix)
|
prefix = getGroupPath(grp.Prefix, prefix)
|
||||||
if len(handlers) > 0 {
|
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.
|
// Route is used to define routes with a common prefix inside the common function.
|
||||||
|
|
|
@ -52,6 +52,7 @@ type Route struct {
|
||||||
root bool // Path equals '/'
|
root bool // Path equals '/'
|
||||||
path string // Prettified path
|
path string // Prettified path
|
||||||
routeParser routeParser // Parameter parser
|
routeParser routeParser // Parameter parser
|
||||||
|
group *Group // Group instance. used for routes in groups
|
||||||
|
|
||||||
// Public fields
|
// Public fields
|
||||||
Method string `json:"method"` // HTTP method
|
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
|
// Uppercase HTTP methods
|
||||||
method = utils.ToUpper(method)
|
method = utils.ToUpper(method)
|
||||||
// Check if the HTTP method is valid unless it's USE
|
// 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,
|
routeParser: parsedPretty,
|
||||||
Params: parsedRaw.params,
|
Params: parsedRaw.params,
|
||||||
|
|
||||||
|
// Group data
|
||||||
|
group: group,
|
||||||
|
|
||||||
// Public data
|
// Public data
|
||||||
Path: pathRaw,
|
Path: pathRaw,
|
||||||
Method: method,
|
Method: method,
|
||||||
|
|
|
@ -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))
|
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) {
|
func Test_Ensure_Router_Interface_Implementation(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue