Add Handler type (#410)

* Add new supporter
* Add new test condition
* Add Handler Type
pull/404/head^2
fenny 2020-05-24 10:02:21 -04:00 committed by GitHub
parent 73a29062ae
commit e8b8fdfb35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 65 additions and 48 deletions

3
.github/README.md vendored
View File

@ -532,9 +532,10 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our
| | User | Donation |
| :---------------------------------------------------------- | :---------------------------------------------- | :------- |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/56607882?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@ankush](https://github.com/ankush) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | ☕ x 1 |

View File

@ -528,9 +528,10 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our
| | User | Donation |
| :---------------------------------------------------------- | :---------------------------------------------- | :------- |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/56607882?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@ankush](https://github.com/ankush) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | ☕ x 1 |

View File

@ -528,9 +528,10 @@ Fiber es un proyecto open source que se mantiene a través de donaciones para pa
| | User | Donation |
| :---------------------------------------------------------- | :---------------------------------------------- | :------- |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/56607882?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@ankush](https://github.com/ankush) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | ☕ x 1 |

View File

@ -528,9 +528,10 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our
| | User | Donation |
| :---------------------------------------------------------- | :---------------------------------------------- | :------- |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/56607882?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@ankush](https://github.com/ankush) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | ☕ x 1 |

View File

@ -530,9 +530,10 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our
| | User | Donation |
| :---------------------------------------------------------- | :---------------------------------------------- | :------- |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/56607882?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@ankush](https://github.com/ankush) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | ☕ x 1 |

View File

@ -532,9 +532,10 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our
| | User | Donation |
| :---------------------------------------------------------- | :---------------------------------------------- | :------- |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/56607882?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@ankush](https://github.com/ankush) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | ☕ x 1 |

View File

@ -532,9 +532,10 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our
| | User | Donation |
| :---------------------------------------------------------- | :---------------------------------------------- | :------- |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/56607882?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@ankush](https://github.com/ankush) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | ☕ x 1 |

View File

@ -532,9 +532,10 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our
| | User | Donation |
| :---------------------------------------------------------- | :---------------------------------------------- | :------- |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/56607882?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@ankush](https://github.com/ankush) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | ☕ x 1 |

View File

@ -528,9 +528,10 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our
| | User | Donation |
| :---------------------------------------------------------- | :---------------------------------------------- | :------- |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/56607882?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@ankush](https://github.com/ankush) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | ☕ x 1 |

View File

@ -526,9 +526,10 @@ Fiber, alan adı, gitbook, netlify, serverless yer sağlayıcısı giderleri ve
| | User | Donation |
| :---------------------------------------------------------- | :---------------------------------------------- | :------- |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/56607882?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@ankush](https://github.com/ankush) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | ☕ x 1 |

View File

@ -531,9 +531,10 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our
| | User | Donation |
| :---------------------------------------------------------- | :---------------------------------------------- | :------- |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/56607882?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| ☕ x 5 |
| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@ankush](https://github.com/ankush) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | ☕ x 3 |
| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | ☕ x 1 |

33
app.go
View File

@ -31,6 +31,9 @@ const Version = "1.10.0"
// Map is a shortcut for map[string]interface{}, usefull for JSON returns
type Map map[string]interface{}
// Handler ...
type Handler = func(*Ctx)
// App denotes the Fiber application.
type App struct {
mutex sync.Mutex
@ -199,68 +202,68 @@ func New(settings ...*Settings) *App {
// - app.Use("/api", handler, handler)
func (app *App) Use(args ...interface{}) *Route {
var prefix string
var handlers []func(*Ctx)
var handlers []Handler
for i := 0; i < len(args); i++ {
switch arg := args[i].(type) {
case string:
prefix = arg
case func(*Ctx):
case Handler:
handlers = append(handlers, arg)
default:
log.Fatalf("Use: Invalid func(c *fiber.Ctx) handler %v", reflect.TypeOf(arg))
log.Fatalf("Use: Invalid Handler %v", reflect.TypeOf(arg))
}
}
return app.register("USE", prefix, handlers...)
}
// Get ...
func (app *App) Get(path string, handlers ...func(*Ctx)) *Route {
func (app *App) Get(path string, handlers ...Handler) *Route {
return app.Add(MethodGet, path, handlers...)
}
// Head ...
func (app *App) Head(path string, handlers ...func(*Ctx)) *Route {
func (app *App) Head(path string, handlers ...Handler) *Route {
return app.Add(MethodHead, path, handlers...)
}
// Post ...
func (app *App) Post(path string, handlers ...func(*Ctx)) *Route {
func (app *App) Post(path string, handlers ...Handler) *Route {
return app.Add(MethodPost, path, handlers...)
}
// Put ...
func (app *App) Put(path string, handlers ...func(*Ctx)) *Route {
func (app *App) Put(path string, handlers ...Handler) *Route {
return app.Add(MethodPut, path, handlers...)
}
// Delete ...
func (app *App) Delete(path string, handlers ...func(*Ctx)) *Route {
func (app *App) Delete(path string, handlers ...Handler) *Route {
return app.Add(MethodDelete, path, handlers...)
}
// Connect ...
func (app *App) Connect(path string, handlers ...func(*Ctx)) *Route {
func (app *App) Connect(path string, handlers ...Handler) *Route {
return app.Add(MethodConnect, path, handlers...)
}
// Options ...
func (app *App) Options(path string, handlers ...func(*Ctx)) *Route {
func (app *App) Options(path string, handlers ...Handler) *Route {
return app.Add(MethodOptions, path, handlers...)
}
// Trace ...
func (app *App) Trace(path string, handlers ...func(*Ctx)) *Route {
func (app *App) Trace(path string, handlers ...Handler) *Route {
return app.Add(MethodTrace, path, handlers...)
}
// Patch ...
func (app *App) Patch(path string, handlers ...func(*Ctx)) *Route {
func (app *App) Patch(path string, handlers ...Handler) *Route {
return app.Add(MethodPatch, path, handlers...)
}
// Add ...
func (app *App) Add(method, path string, handlers ...func(*Ctx)) *Route {
func (app *App) Add(method, path string, handlers ...Handler) *Route {
return app.register(method, path, handlers...)
}
@ -270,7 +273,7 @@ func (app *App) Static(prefix, root string, config ...Static) *Route {
}
// All ...
func (app *App) All(path string, handlers ...func(*Ctx)) []*Route {
func (app *App) All(path string, handlers ...Handler) []*Route {
routes := make([]*Route, len(methodINT))
for method, i := range methodINT {
routes[i] = app.Add(method, path, handlers...)
@ -279,7 +282,7 @@ func (app *App) All(path string, handlers ...func(*Ctx)) []*Route {
}
// Group is used for Routes with common prefix to define a new sub-router with optional middleware.
func (app *App) Group(prefix string, handlers ...func(*Ctx)) *Group {
func (app *App) Group(prefix string, handlers ...Handler) *Group {
if len(handlers) > 0 {
app.register("USE", prefix, handlers...)
}

View File

@ -19,72 +19,72 @@ type Group struct {
// Middleware matches requests beginning with the provided prefix.
// Providing a prefix is optional, it defaults to "/".
//
// - app.Use(handler)
// - app.Use("/api", handler)
// - app.Use("/api", handler, handler)
// - group.Use(handler)
// - group.Use("/api", handler)
// - group.Use("/api", handler, handler)
func (grp *Group) Use(args ...interface{}) *Route {
var path = ""
var handlers []func(*Ctx)
var handlers []Handler
for i := 0; i < len(args); i++ {
switch arg := args[i].(type) {
case string:
path = arg
case func(*Ctx):
case Handler:
handlers = append(handlers, arg)
default:
log.Fatalf("Use: Invalid func(c *fiber.Ctx) handler %v", reflect.TypeOf(arg))
log.Fatalf("Use: Invalid Handler %v", reflect.TypeOf(arg))
}
}
return grp.app.register("USE", getGroupPath(grp.prefix, path), handlers...)
}
// Get ...
func (grp *Group) Get(path string, handlers ...func(*Ctx)) *Route {
func (grp *Group) Get(path string, handlers ...Handler) *Route {
return grp.Add(MethodGet, path, handlers...)
}
// Head ...
func (grp *Group) Head(path string, handlers ...func(*Ctx)) *Route {
func (grp *Group) Head(path string, handlers ...Handler) *Route {
return grp.Add(MethodHead, path, handlers...)
}
// Post ...
func (grp *Group) Post(path string, handlers ...func(*Ctx)) *Route {
func (grp *Group) Post(path string, handlers ...Handler) *Route {
return grp.Add(MethodPost, path, handlers...)
}
// Put ...
func (grp *Group) Put(path string, handlers ...func(*Ctx)) *Route {
func (grp *Group) Put(path string, handlers ...Handler) *Route {
return grp.Add(MethodPut, path, handlers...)
}
// Delete ...
func (grp *Group) Delete(path string, handlers ...func(*Ctx)) *Route {
func (grp *Group) Delete(path string, handlers ...Handler) *Route {
return grp.Add(MethodDelete, path, handlers...)
}
// Connect ...
func (grp *Group) Connect(path string, handlers ...func(*Ctx)) *Route {
func (grp *Group) Connect(path string, handlers ...Handler) *Route {
return grp.Add(MethodConnect, path, handlers...)
}
// Options ...
func (grp *Group) Options(path string, handlers ...func(*Ctx)) *Route {
func (grp *Group) Options(path string, handlers ...Handler) *Route {
return grp.Add(MethodOptions, path, handlers...)
}
// Trace ...
func (grp *Group) Trace(path string, handlers ...func(*Ctx)) *Route {
func (grp *Group) Trace(path string, handlers ...Handler) *Route {
return grp.Add(MethodTrace, path, handlers...)
}
// Patch ...
func (grp *Group) Patch(path string, handlers ...func(*Ctx)) *Route {
func (grp *Group) Patch(path string, handlers ...Handler) *Route {
return grp.Add(MethodPatch, path, handlers...)
}
// Add ...
func (grp *Group) Add(method, path string, handlers ...func(*Ctx)) *Route {
func (grp *Group) Add(method, path string, handlers ...Handler) *Route {
return grp.app.register(method, getGroupPath(grp.prefix, path), handlers...)
}
@ -94,7 +94,7 @@ func (grp *Group) Static(prefix, root string, config ...Static) *Route {
}
// All ...
func (grp *Group) All(path string, handlers ...func(*Ctx)) []*Route {
func (grp *Group) All(path string, handlers ...Handler) []*Route {
routes := make([]*Route, len(methodINT))
for method, i := range methodINT {
routes[i] = grp.Add(method, path, handlers...)
@ -103,7 +103,7 @@ func (grp *Group) All(path string, handlers ...func(*Ctx)) []*Route {
}
// Group is used for Routes with common prefix to define a new sub-router with optional middleware.
func (grp *Group) Group(prefix string, handlers ...func(*Ctx)) *Group {
func (grp *Group) Group(prefix string, handlers ...Handler) *Group {
prefix = getGroupPath(grp.prefix, prefix)
if len(handlers) > 0 {
grp.app.register("USE", prefix, handlers...)

View File

@ -24,9 +24,9 @@ type Route struct {
routeParams []string // Case sensitive param keys
// Public fields
Path string // Original registered route path
Method string // HTTP method
Handlers []func(*Ctx) // Ctx handlers
Path string // Original registered route path
Method string // HTTP method
Handlers []Handler // Ctx handlers
}
func (r *Route) match(path, original string) (match bool, values []string) {
@ -116,7 +116,7 @@ func (app *App) handler(rctx *fasthttp.RequestCtx) {
app.ReleaseCtx(ctx)
}
func (app *App) register(method, pathRaw string, handlers ...func(*Ctx)) *Route {
func (app *App) register(method, pathRaw string, handlers ...Handler) *Route {
// Uppercase HTTP methods
method = utils.ToUpper(method)
// Check if the HTTP method is valid unless it's USE

View File

@ -61,6 +61,9 @@ func Test_Utils_getGroupPath(t *testing.T) {
res := getGroupPath("/v1", "/")
utils.AssertEqual(t, "/v1", res)
res = getGroupPath("/v1/", "/")
utils.AssertEqual(t, "/v1/", res)
res = getGroupPath("/v1", "/")
utils.AssertEqual(t, "/v1", res)