Open dennisvanderweide opened 10 months ago
I have the same issue
This behavior is due to the way the chi router handles middleware and route patterns. When you register a middleware using r.Use() at the root level, the middleware is applied to all routes, including routes that do not have any URL parameters. As a result, when the middleware tries to extract the "id" parameter using chi.URLParam(r, "id"), it doesn't find it because the current route doesn't have an "id" parameter.
The behavior you describe would be what I would expect to be the behavior, but the problem is that when I execute an HTTP request for a route which does have an id
parameter, it won't be able to find the parameter even though the route does contain a parameter.
mx.URLParams
gets populated only at the routeHTTP
function which will not get the id
param if your middleware is at the top level (*
route). Try this instead:
v1Router := chi.NewRouter()
v1Router.Route("/test/{id}", func(r chi.Router) {
r.Use(Middleware)
r.Get("/", handler.getHandler)
r.Patch("/", handler.updateHandler)
r.Delete("/", handler.deleteHandler)
})
Thanks! That works but is super optimal. I need to repeat the middleware call for every endpoint group.
Example:
v1Router := chi.NewRouter()
v1Router.Route("/test/{id}", func(r chi.Router) {
r.Use(Middleware)
r.Get("/", handler.getHandler)
r.Patch("/", handler.updateHandler)
r.Delete("/", handler.deleteHandler)
})
v1Router := chi.NewRouter()
v1Router.Route("/another-test/{id}", func(r chi.Router) {
r.Use(Middleware)
r.Get("/", handler.getHandler)
r.Patch("/", handler.updateHandler)
r.Delete("/", handler.deleteHandler)
})
That is a problem because I want to ensure that the middleware (authZ) is called on every request. Do I miss anything here or is there a better way to get the URL params in the middleware (I need the params to make a call on the authZ).
When I create a middleware to log the
id
URL parameter, which exists in the route I request, the value is always empty. I do get a value inside the handler itselfr := chi.NewRouter() r.Use(func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") log.Println(id) h.ServeHTTP(w, r) }) }) r.Get("/test/{id}", func(w http.ResponseWriter, r *http.Request) { id := router.Param(r, "id").String() io.WriteString(w, id) })
When I move this code to a
Group
, the URL param will become available inside the middleware.r := chi.NewRouter() r.Group(func(r chi.Router) { r.Use(func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") log.Println(id) h.ServeHTTP(w, r) }) }) r.Get("/test/{id}", func(w http.ResponseWriter, r *http.Request) { id := router.Param(r, "id").String() io.WriteString(w, id) }) })
I think this behavior is quite strange and prone to errors
Tested with the latest version (5.0.11)
@jfcdigitalventures You could wrap everything in a Group
just like in my example here, but it's a workaround, not a fix.
I still think it's weird that a middleware on the root behaves different than middleware on every other level. My suggestion would be to fix this, so this behaviour will be the same whenever you use a middleware.
When I create a middleware to log the
id
URL parameter, which exists in the route I request, the value is always empty. I do get a value inside the handler itselfWhen I move this code to a
Group
, the URL param will become available inside the middleware.I think this behavior is quite strange and prone to errors
Tested with the latest version (5.0.11)