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?