My simplified routing is similar to
r.Route("/api/v1", func(r chi.Router) {
r.Route("/case", func(r chi.Router) {
// generic case - for everyone
r.Get("/{uuid}", caseGetByUuid)
r.Put("/", casePut)
// all cases only available to admins
// r.Use(ensureAdminUser) // ← this is the place I have an error
r.Get("/", caseGetAll)
}
// admin endpoint
r.Route("/admin", func(r chi.Router) {
// ensure that the user is an admin
r.Use(ensureAdminUser)
r.Route("/user", func(r chi.Router) {
r.Route("/token", func(r chi.Router) { // /admin/user/token
r.Get("/", userTokenGetAll)
r.Put("/", userTokenCreate)
r.Delete("/", userTokenDelete)
})
})
})
})
The second route (/admin
) is restricted by a middleware that will break the chain if specific constraints are not met. The middleware is placed ahead of all the routes.
I wanted to do similar filtering in the first route (/case
), but only for one route (out of the three). Uncommenting r.Use(ensureAdminUser)
leads to
panic: chi: all middlewares must be defined before routes on a mux
I cannot have two routes for /case
either.
Is there a way to keep the route /case
and restrict one of the methods for the root call?
If not I will create an alternative route for the restricted case.
CodePudding user response:
You can wrap the middleware and subsequent routes in their own group (emphasis mine):
// Group adds a new inline-Router along the current routing
// path, with a fresh middleware stack for the inline-Route.
Group(fn func(r Router)) Router
r.Route("/api/v1", func(r chi.Router) {
r.Route("/case", func(r chi.Router) {
// generic case - for everyone
r.Get("/{uuid}", caseGetByUuid)
r.Put("/", casePut)
// all cases only available to admins
r.Group(func(r chi.Router) {
r.Use(ensureAdminUser)
r.Get("/", caseGetAll)
})
}
})
It will work also with a sub-router with r.Route
.
Another option when a middleware is applied to only one route is r.With
which allows you to “inline” the middleware:
r.Route("/api/v1", func(r chi.Router) {
r.Route("/case", func(r chi.Router) {
// generic case - for everyone
r.Get("/{uuid}", caseGetByUuid)
r.Put("/", casePut)
// all cases only available to admins
r.With(ensureAdminUser).Get("/", caseGetAll)
}
})