Nesting subrouters in Gorilla Mux
Asked Answered
F

3

23

I've been using gorilla/mux for my routing needs. But I noticed one problem, when I nest multiple Subrouters it doesn't work.

Here is the example:

func main() {
    r := mux.NewRouter().StrictSlash(true)
    api := r.Path("/api").Subrouter()
    u := api.Path("/user").Subrouter()
    u.Methods("GET").HandleFunc(UserHandler)
    http.ListenAndServe(":8080", r)
}

I wanted to use this approach so I can delegate populating the router to some other package, for example user.Populate(api)

However this doesn't seem to work. It works only if I use single Subrouter in the chain.

Any ideas?

Flutter answered 11/4, 2015 at 8:53 Comment(0)
F
38

I figured it out, so I'll just post it here in case someone is as stupid as I was. :D

When creating path-based subrouter, you have to obtain it with PathPrefix instead of Path.

r.PathPrefix("/api").Subrouter()

Use r.Path("/api") only when attaching handlers to that endpoint.

Flutter answered 11/4, 2015 at 12:53 Comment(0)
U
3

For those who are struggling to split between auth and noauth routes, the following works fine for me:

r := mux.NewRouter()

noAuthRouter := r.MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) bool {
    return r.Header.Get("Authorization") == ""
}).Subrouter()

authRouter := r.MatcherFunc(func(r *http.Request, rm *mux.RouteMatch) bool {
    return true
}).Subrouter()

Then you can apply middleware for authRouter only

Unknow answered 22/1, 2021 at 14:40 Comment(0)
L
-1

If you need to Separate out the UI and API routers, you can simply do what the OP suggested:

appRouter := r.PathPrefix("/").Subrouter()
appRouter.Use(myAppRouter)
apiRouter := r.PathPrefix("/api").Subrouter()
apiRouter.Use(myAPIRouter)

Many thanks for the OP for providing the answer. Hopefully having it all in one place for my use case will help someone.

Lunatic answered 30/3, 2020 at 23:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.