I have a golang api application. I've defined a set of routes and handlers. However, the mux router only ever returns the last route.
When I request /api/info
I get this in my logging:
9:0:38 app | 2018/02/05 09:00:38 GET /api/info Users Create 308.132µs
Why is that routing to the wrong route?
routing package:
// NewRouter establishes the root application router
func NewRouter(context *config.ApplicationContext, routes Routes, notFoundHandler http.HandlerFunc) *mux.Router {
router := mux.NewRouter()
router.NotFoundHandler = notFoundHandler
for _, route := range routes {
router.
PathPrefix("/api").
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
// TODO: fix HandlerFunc. Right now, it is overriding previous routes and setting a single handler for all
// this means that the last route is the only router with a handler
HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logRoute(setJSONHeader(route.HandlerFunc), route.Name)(context, w, r)
})
}
return router
}
func logRoute(inner ContextHandlerFunc, name string) ContextHandlerFunc {
return func(c *config.ApplicationContext, w http.ResponseWriter, r *http.Request) {
start := time.Now()
inner(c, w, r)
log.Printf(
"%s\t%s\t%s\t%s",
r.Method,
r.RequestURI,
name,
time.Since(start),
)
}
}
func setJSONHeader(inner ContextHandlerFunc) ContextHandlerFunc {
return func(c *config.ApplicationContext, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
inner(c, w, r)
}
}
main package:
var context = config.ApplicationContext{
Database: database.NewDatabase().Store,
}
var routes = router.Routes{
router.Route{"Info", "GET", "/info", handlers.InfoShow},
router.Route{"Users Create", "POST", "/users/create", handlers.UsersCreate},
}
func main() {
notFoundHandler := handlers.Errors404
router := router.NewRouter(&context, routes, notFoundHandler)
port := os.Getenv("PORT")
log.Fatal(http.ListenAndServe(":"+port, router))
}
If I visit /api/info
it will attempt to call a POST to /users/create
. However, if I remove the second route, it will correctly route to the InfoShow
handler.
Why is mux overriding the first route? I'm fairly certain there's something wrong with
HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logRoute(setJSONHeader(route.HandlerFunc), route.Name)(context, w, r)
})
but I'm not sure why that would cause it to map over the first route.
Ideas?
mux
package you are using. – leaf beboprouter := router.NewRouter(&context, routes, notFoundHandler)
. You're shadowing therouter
package with therouter
variable. Name them differently. As a matter of practice, it's recommended to not name your packages after what someone would naturally name the type from that package. Instead of router, use therouting
name you specified in the OP. Will make for less confusing code. – Kaedys