Add route naming feature. (#1650)

* Add route naming feature.

* Update basicauth_test.go

* Fix gosec issues.

* Change RoutaName -> Name

* Fix race conditions.

* Update READMEs.
pull/1672/head
M. Efe Çetin 2021-12-28 16:04:04 +03:00 committed by GitHub
parent 03c9598f6e
commit 68d3b773bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 600 additions and 3 deletions

30
.github/README.md vendored
View File

@ -191,6 +191,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**Serving Static Files**](https://docs.gofiber.io/api/app#static)
```go

30
.github/README_de.md vendored
View File

@ -189,6 +189,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**Serving Static Files**](https://docs.gofiber.io/api/app#static)
```go

30
.github/README_es.md vendored
View File

@ -189,6 +189,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**Sirviendo Archivos Estáticos**](https://docs.gofiber.io/api/app#static)
```go

35
.github/README_fa.md vendored
View File

@ -240,6 +240,41 @@ func main() {
</div>
<div dir="ltr" >
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
</div>
#### 📖 [**Serving Static Files**](https://docs.gofiber.io/api/app#static)
<div dir="ltr">

30
.github/README_fr.md vendored
View File

@ -191,6 +191,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**Serving Static Files**](https://docs.gofiber.io/api/app#static)
```go

34
.github/README_he.md vendored
View File

@ -246,6 +246,40 @@ func main() {
<div dir="rtl">
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
</div>
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
<div dir="rtl">
#### 📖 [**Serving Static Files**](https://docs.gofiber.io/api/app#static)
</div>

30
.github/README_id.md vendored
View File

@ -191,6 +191,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**Serving File Static**](https://docs.gofiber.io/api/app#static)
```go

30
.github/README_it.md vendored
View File

@ -190,6 +190,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**Servire File Statici**](https://docs.gofiber.io/api/app#static)
```go

30
.github/README_ja.md vendored
View File

@ -194,6 +194,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**静的ファイルの提供**](https://docs.gofiber.io/api/app#static)
```go

30
.github/README_ko.md vendored
View File

@ -195,6 +195,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**Serving Static Files**](https://docs.gofiber.io/api/app#static)
```go

30
.github/README_nl.md vendored
View File

@ -195,6 +195,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**Serving Static Files**](https://docs.gofiber.io/api/app#static)
```go

30
.github/README_pt.md vendored
View File

@ -191,6 +191,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**Servindo arquivos estáticos**](https://docs.gofiber.io/api/app#static)
```go

30
.github/README_ru.md vendored
View File

@ -191,6 +191,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**Serving Static Files**](https://docs.gofiber.io/api/app#static)
```go

34
.github/README_sa.md vendored
View File

@ -209,6 +209,40 @@ func main() {
</div>
<div dir="ltr" >
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
</div>
#### 📖 [**Serving Static Files**](https://docs.gofiber.io/api/app#static)
<div dir="ltr">

30
.github/README_tr.md vendored
View File

@ -190,6 +190,36 @@ func main() {
```
#### 📖 [**Route İsimlendirmesi**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ kayit
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Cikti:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**Statik Dosya Sunumu**](https://docs.gofiber.io/api/app#static)
```go

View File

@ -191,6 +191,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**静态文件**](https://docs.gofiber.io/api/app#static)服务
```go

View File

@ -193,6 +193,36 @@ func main() {
```
#### 📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)
```go
func main() {
app := fiber.New()
// GET /api/register
app.Get("/api/*", func(c *fiber.Ctx) error {
msg := fmt.Sprintf("✋ %s", c.Params("*"))
return c.SendString(msg) // => ✋ register
}).Name("api")
data, _ := json.MarshalIndent(app.GetRoute("api"), "", " ")
fmt.Print(string(data))
// Prints:
// {
// "method": "GET",
// "name": "api",
// "path": "/api/*",
// "params": [
// "*1"
// ]
// }
log.Fatal(app.Listen(":3000"))
}
```
#### 📖 [**Serving Static Files**](https://docs.gofiber.io/api/app#static)
```go

32
app.go
View File

@ -398,6 +398,14 @@ const (
DefaultCompressedFileSuffix = ".fiber.gz"
)
// Variables for Name & GetRoute
var latestRoute struct {
route *Route
mu sync.Mutex
}
var latestGroup Group
// DefaultErrorHandler that process return errors from handlers
var DefaultErrorHandler = func(c *Ctx, err error) error {
code := StatusInternalServerError
@ -537,6 +545,30 @@ func (app *App) Mount(prefix string, fiber *App) Router {
return app
}
// Assign name to specific route.
func (app *App) Name(name string) Router {
if strings.HasPrefix(latestRoute.route.path, latestGroup.prefix) {
latestRoute.route.Name = latestGroup.name + name
} else {
latestRoute.route.Name = name
}
return app
}
// Get route by name
func (app *App) GetRoute(name string) Route {
for _, routes := range app.stack {
for _, route := range routes {
if route.Name == name {
return *route
}
}
}
return Route{}
}
// Use registers a middleware route that will match requests
// with the provided prefix (which is optional and defaults to "/").
//

View File

@ -519,6 +519,31 @@ func Test_App_Methods(t *testing.T) {
testStatus200(t, app, "/john/doe", MethodGet)
}
func Test_App_Route_Naming(t *testing.T) {
app := New()
handler := func(c *Ctx) error {
return c.SendStatus(StatusOK)
}
app.Get("/john", handler).Name("john")
app.Delete("/doe", handler)
app.Name("doe")
jane := app.Group("/jane").Name("jane.")
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")
utils.AssertEqual(t, "post", app.GetRoute("post").Name)
utils.AssertEqual(t, "john", app.GetRoute("john").Name)
utils.AssertEqual(t, "jane.test", app.GetRoute("jane.test").Name)
utils.AssertEqual(t, "jane.trace", app.GetRoute("jane.trace").Name)
utils.AssertEqual(t, "test", app.GetRoute("test").Name)
}
func Test_App_New(t *testing.T) {
app := New()
app.Get("/", testEmptyHandler)

View File

@ -656,7 +656,7 @@ func (a *Agent) Reuse() *Agent {
func (a *Agent) InsecureSkipVerify() *Agent {
if a.HostClient.TLSConfig == nil {
/* #nosec G402 */
a.HostClient.TLSConfig = &tls.Config{InsecureSkipVerify: true}
a.HostClient.TLSConfig = &tls.Config{InsecureSkipVerify: true} // #nosec G402
} else {
/* #nosec G402 */
a.HostClient.TLSConfig.InsecureSkipVerify = true

View File

@ -14,6 +14,7 @@ import (
type Group struct {
app *App
prefix string
name string
}
// Mount attaches another app instance as a sub-router along a routing path.
@ -33,6 +34,14 @@ func (grp *Group) Mount(prefix string, fiber *App) Router {
return grp
}
// Assign name to specific route.
func (grp *Group) Name(name string) Router {
grp.name = name
latestGroup = *grp
return grp
}
// Use registers a middleware route that will match requests
// with the provided prefix (which is optional and defaults to "/").
//

View File

@ -68,7 +68,8 @@ func getTlsConfig(ln net.Listener) *tls.Config {
// Get private field from value
if field := val.FieldByName("config"); field.Type() != nil {
// Copy value from pointer field (unsafe)
if newval := reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())); newval.Type() != nil {
newval := reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())) // #nosec G103
if newval.Type() != nil {
// Get element from pointer
if elem := newval.Elem(); elem.Type() != nil {
// Cast value to *tls.Config

View File

@ -79,7 +79,7 @@ func (app *App) prefork(network, addr string, tlsConfig *tls.Config) (err error)
// launch child procs
for i := 0; i < max; i++ {
/* #nosec G204 */
cmd := exec.Command(os.Args[0], os.Args[1:]...)
cmd := exec.Command(os.Args[0], os.Args[1:]...) // #nosec G204
if testPreforkMaster {
// When test prefork master,
// just start the child process with a dummy cmd,

View File

@ -37,6 +37,8 @@ type Router interface {
Group(prefix string, handlers ...Handler) Router
Mount(prefix string, fiber *App) Router
Name(name string) Router
}
// Route is a struct that holds all metadata for each registered handler
@ -51,6 +53,7 @@ type Route struct {
// Public fields
Method string `json:"method"` // HTTP method
Name string `json:"name"` // Route's name
Path string `json:"path"` // Original registered route path
Params []string `json:"params"` // Case sensitive param keys
Handlers []Handler `json:"-"` // Ctx handlers
@ -425,6 +428,10 @@ func (app *App) addRoute(method string, route *Route) {
app.stack[m] = append(app.stack[m], route)
app.routesRefreshed = true
}
latestRoute.mu.Lock()
latestRoute.route = route
latestRoute.mu.Unlock()
}
// buildTree build the prefix tree from the previously registered routes