Fiber version
1.12.6
Issue description
Nested Route paths not invoking the correct handler.
Code snippet
func SetupRoutes(app *fiber.App) {
todo := app.Group("/todo", middleware.Logger())
todo.Get("/:id", handler.ReadTodo)
todo.Post("/", handler.CreateTodo)
todo.Put("/:id", handler.UpdateTodo)
todo.Delete("/:id", handler.DeleteTodo)
todo.Get("/all/todos", handler.ReadAllTodo)
todo.Get("/all", handler.DummyAllHandler) // this does not working, it always invoking todo.Get("/:id", handler.ReadTodo)
}
It is probably taking your path "all" as the id parameter. Being in the same method I assume that you must be taking it this way id = "all". Try putting using StrictRouting.
app := fiber.New(&fiber.Settings{
StrictRouting: true,
})
Thanks for your reporting! But I don't it is counted as a bug.
According to your example, there are two approaches to solve the problem:
package main
import (
"strconv"
"github.com/gofiber/fiber"
)
func main() {
app := fiber.New()
// get /option1/all => "all"
app.Get("/option1/all", func(c *fiber.Ctx) { c.SendString("all") })
// get /option1/1 => "1"
app.Get("/option1/:id", func(c *fiber.Ctx) { c.Send(c.Params("id")) })
// get /option2/1 => "1"
app.Get("/option2/:id", func(c *fiber.Ctx) {
// assume id is integer
if id, err := strconv.Atoi(c.Params("id")); err != nil {
c.Next()
} else {
c.Send(id)
}
})
// get /option2/all => "all"
app.Get("/option2/all", func(c *fiber.Ctx) { c.SendString("all") })
app.Listen(3000)
}
You can place routes in the appropriate order so that Fiber can do the right thing :smile:
@solrac97gr
It is probably taking your path "all" as the id parameter. Being in the same method I assume that you must be taking it this way id = "all". Try putting using StrictRouting.
app := fiber.New(&fiber.Settings{ StrictRouting: true, })
app := fiber.New(&fiber.Settings{
StrictRouting: true,
})
setting StrictRouting: true does not fix the problem still invoking todo.Get("/:id", handler.ReadTodo)
@mohanasundaramn follow the @kiyonlin solution. That will fix that.
Thanks for your reporting! But I don't it is counted as a bug.
According to your example, there are two approaches to solve the problem:
package main import ( "strconv" "github.com/gofiber/fiber" ) func main() { app := fiber.New() // get /option1/all => "all" app.Get("/option1/all", func(c *fiber.Ctx) { c.SendString("all") }) // get /option1/1 => "1" app.Get("/option1/:id", func(c *fiber.Ctx) { c.Send(c.Params("id")) }) // get /option2/1 => "1" app.Get("/option2/:id", func(c *fiber.Ctx) { // assume id is integer if id, err := strconv.Atoi(c.Params("id")); err != nil { c.Next() } else { c.Send(id) } }) // get /option2/all => "all" app.Get("/option2/all", func(c *fiber.Ctx) { c.SendString("all") }) app.Listen(3000) }You can place routes in the appropriate order so that
Fibercan do the right thing 馃槃
// get /option1/all => "all"
app.Get("/option1/all", func(c *fiber.Ctx) { c.SendString("all") })
Seems this is not working
package main
import (
"strconv"
"github.com/gofiber/fiber"
)
func getAll(c *fiber.Ctx) { c.SendString("option all") }
func getById(c *fiber.Ctx) { c.Send(c.Params("id")) }
func setupRoutes(a *fiber.App) {
option := a.Group("/option")
option.Get("/:id", getById)
option.Get("/all", getAll)
option2 := a.Group("/options2")
option2.Get("/all", func(c *fiber.Ctx) { c.SendString("option2 all") })
option2.Get("/:id", func(c *fiber.Ctx) {
// assume id is integer
if id, err := strconv.Atoi(c.Params("id")); err != nil {
c.Next()
} else {
c.Send(id)
}
})
}
func main() {
app := fiber.New()
setupRoutes(app)
app.Listen(3000)
}
But if I change the order of option/all option/:id it works. why is that?
package main
import (
"strconv"
"github.com/gofiber/fiber"
)
func getAll(c *fiber.Ctx) { c.SendString("option all") }
func getById(c *fiber.Ctx) { c.Send(c.Params("id")) }
func setupRoutes(a *fiber.App) {
option := a.Group("/option")
option.Get("/all", getAll)
option.Get("/:id", getById)
option2 := a.Group("/options2")
option2.Get("/all", func(c *fiber.Ctx) { c.SendString("option2 all") })
option2.Get("/:id", func(c *fiber.Ctx) {
// assume id is integer
if id, err := strconv.Atoi(c.Params("id")); err != nil {
c.Next()
} else {
c.Send(id)
}
})
}
func main() {
app := fiber.New()
setupRoutes(app)
app.Listen(3000)
}
Hi @mohanasundaramn
Seems this is not working
option := a.Group("/option")
option.Get("/:id", getById)
option.Get("/all", getAll)
When you put /:id above /all, you should do the Next thing. But your first example just do the opposite.
Btw @mohanasundaramn
But if I change the order of
option/alloption/:idit works. why is that?
That is because Fiber always finds the first route to match the request's path and breaks the route chain if there is no more Next is called.
@solrac97gr @kiyonlin Can you please try both codes, I still believe this is a bug
@solrac97gr @kiyonlin Can you please try both codes, I still believe this is a bug
I adjusted your code:
package main
import (
"strconv"
"github.com/gofiber/fiber"
)
func getAll(c *fiber.Ctx) { c.SendString("option all") }
func getById(c *fiber.Ctx) { c.Send(c.Params("id")) }
func setupRoutes(a *fiber.App) {
option := a.Group("/option")
// 馃憢馃憢馃憢 get /options/all => option all
option.Get("/all", getAll)
// 馃憢馃憢馃憢 get /options/1 => 1
option.Get("/:id", getById)
option2 := a.Group("/option2")
// 馃憢馃憢馃憢 get /option2/2 => 2
option2.Get("/:id", func(c *fiber.Ctx) {
// assume id is integer
if id, err := strconv.Atoi(c.Params("id")); err != nil {
c.Next()
} else {
c.Send(id)
}
})
// 馃憢馃憢馃憢 get /option2/all => option2 all
option2.Get("/all", func(c *fiber.Ctx) { c.SendString("option2 all") })
}
func main() {
app := fiber.New()
setupRoutes(app)
app.Listen(3000)
}
@mohanasundaramn Problem sovled?
Feel free to close this issue if you don't have further questions 馃憤
option := a.Group("/option")
option.Get("/:id", getById)
option.Get("/all", getAll)
But why it is not working in the above case.
I am new to golang, I choose fiber coz it gives express(nodejs) like experience.
The above case is still a bug, right?
Is there any plan for a fix, or at least it needs to mention somewhere in the documentation
Can I use Fiber for the production application?
option := a.Group("/option") option.Get("/:id", getById) option.Get("/all", getAll)But why it is not working in the above case.
I am new togolang, I choosefibercoz it givesexpress(nodejs)like experience.
The above case is still a bug, right?
Is there any plan for a fix, or at least it needs to mention somewhere in the documentation
Nope, as I said above.
That is because
Fiberalways finds the first route to match the request's path and breaks the route chain if there is no more Next is called.
Can I use
Fiberfor the production application?
Definately sure.
@kiyonlin Thank you for your time.
option := a.Group("/option") option.Get("/:id", getById) option.Get("/all", getAll)But why it is not working in the above case.
I am new togolang, I choosefibercoz it givesexpress(nodejs)like experience.
The above case is still a bug, right?
Is there any plan for a fix, or at least it needs to mention somewhere in the documentation
The presented case above would have the same results in Expressjs, /:id also matches /all.
@kiyonlin explained this perfectly, just like in Express: order matters :+1:
Most helpful comment
The presented case above would have the same results in Expressjs,
/:idalso matches/all.@kiyonlin explained this perfectly, just like in Express: order matters :+1: