While fiddling around with gofiber (v2) to learn about it - going through the official docs and trying stuff out; printing all the routes with GetRoutes()
returns all the routes but twice.
There is no mention of this anywhere in the docs, and logically this should not be the case. As a beginner to gofiber I cannot understand why this is.
// file = main.go
package main
import (
"encoding/json"
"fmt"
"log"
"time"
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New()
// serving static files
app.Static("/static", "./public", fiber.Static{
Compress: true,
ByteRange: true,
Browse: true,
Index: "index.html",
CacheDuration: 10 * time.Second,
MaxAge: 3600,
}).Name("static")
// Grouping APIs into their versions
v1 := app.Group("/api/v1")
v1.Name("api-v1-")
v1.Get("/list", func(c *fiber.Ctx) error {
return c.SendString("v1: /list")
}).Name("list")
v1.Get("/user", func(c *fiber.Ctx) error {
return c.SendString("v1: /user")
}).Name("user")
v2 := app.Group("/api/v2")
v2.Name("api-v2-")
v2.Get("/list", func(c *fiber.Ctx) error {
return c.SendString("v2: /list")
}).Name("list")
v2.Get("/user", func(c *fiber.Ctx) error {
return c.SendString("v2: /user")
}).Name("user")
// Routes
app.Route("/route", func(router fiber.Router) {
router.Get("/foo", func(c *fiber.Ctx) error {
return c.SendString("/route/foo")
}).Name("route-foo")
router.Get("/bar", func(c *fiber.Ctx) error {
return c.SendString("/route/bar")
}).Name("route-bar")
})
// GetRoutes -> Get all Routes
data, _ := json.MarshalIndent(app.GetRoutes(true), "", " ")
fmt.Println(string(data))
log.Fatal(app.Listen(":3000"))
}
[
{
"method": "GET",
"name": "api-v1-list",
"path": "/api/v1/list",
"params": null
},
{
"method": "GET",
"name": "api-v1-user",
"path": "/api/v1/user",
"params": null
},
{
"method": "GET",
"name": "api-v2-list",
"path": "/api/v2/list",
"params": null
},
{
"method": "GET",
"name": "api-v2-user",
"path": "/api/v2/user",
"params": null
},
{
"method": "GET",
"name": "route-foo",
"path": "/route/foo",
"params": null
},
{
"method": "GET",
"name": "route-bar",
"path": "/route/bar",
"params": null
},
{
"method": "HEAD",
"name": "api-v1-list",
"path": "/api/v1/list",
"params": null
},
{
"method": "HEAD",
"name": "api-v1-user",
"path": "/api/v1/user",
"params": null
},
{
"method": "HEAD",
"name": "api-v2-list",
"path": "/api/v2/list",
"params": null
},
{
"method": "HEAD",
"name": "api-v2-user",
"path": "/api/v2/user",
"params": null
},
{
"method": "HEAD",
"name": "route-foo",
"path": "/route/foo",
"params": null
},
{
"method": "HEAD",
"name": "route-bar",
"path": "/route/bar",
"params": null
}
]
┌───────────────────────────────────────────────────┐
│ Fiber v2.52.8 │
│ http://127.0.0.1:3000 │
│ (bound on host 0.0.0.0 and port 3000) │
│ │
│ Handlers ............ 13 Processes ........... 1 │
│ Prefork ....... Disabled PID ............... 256 │
└───────────────────────────────────────────────────┘
As seen, each of the route is listed twice. Why is this the case?
It doesn't - it shows you the HEAD route and the GET route.
The
HEAD
HTTP method requests the metadata of a resource in the form of headers that the server would have sent if theGET
method was used instead. This method can be used in cases where a URL might produce a large download, for example, aHEAD
request can read theContent-Length
header to check the file size before downloading the file with aGET
.
In gofiber, when you register a GET route, it automatically adds the HEAD route as well:
https://github.com/gofiber/fiber/blob/f4a9cb5023b871430b669d5ca36db1478033dad4/app.go#L707-L711
// Get registers a route for GET methods that requests a representation
// of the specified resource. Requests using GET should only retrieve data.
func (app *App) Get(path string, handlers ...Handler) Router {
return app.Head(path, handlers...).Add(MethodGet, path, handlers...)
}