Gilla Gorilla Nested Router Not Working

Using the code below, when I access / test 2, it answers 404 - not found. / test 1 is working correctly. Why is this? Is nesting not allowed even though routers implement the http.Handler interface?

package main import ( "fmt" "net/http" "github.com/gorilla/mux" ) func main() { mainRouter := mux.NewRouter() subRouter := mux.NewRouter() mainRouter.HandleFunc("/test1", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "test1") }) subRouter.HandleFunc("/test2", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "test2") }) mainRouter.Handle("/", subRouter) http.ListenAndServe(":9999", mainRouter) } 

EDIT:

My main goal was to add some initial work, which would be common to all routes in the subRouter and only for them. To be more specific, I would like to use Negroni as my intermediate logger. Negroni has an example of adding middleware to a route group:

 router := mux.NewRouter() adminRoutes := mux.NewRouter() // add admin routes here Create a new negroni for the admin middleware router.Handle("/admin", negroni.New( Middleware1, Middleware2, negroni.Wrap(adminRoutes), )) 

Negroni basically executes ServeHTTP methods for each argument, since they all implement http.Handler. It runs them in order, so the router routes will be the last.

I am familiar with the concept of Subrouter in Mux, but AFAIK I cannot use it in the same way as the example above, in particular, I can not enter anything between mainRouter and its Subrouter . This is why nesting looks more flexible.

+6
source share
4 answers

I know this question is somewhat old, but I spent some time figuring out how handlers work and compatible work. You can see the experiment code here .

Basically, you can get the effect you want with the code:

 package main import ( "fmt" "net/http" "github.com/gorilla/mux" ) func main() { mainRouter := mux.NewRouter() subRouter := mux.NewRouter() mainRouter.HandleFunc("/test1", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "test1") }) subRouter.HandleFunc("/test2", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "test2") }) // in mux, you need to register subrouter // with the same path that the handlers in // it are matching mainRouter.Handle("/test2", subRouter) // if your subrouter has handlers that match // other sub paths - you also need to do this mainRouter.Handle("/test2/{_dummy:.*}", subRouter) http.ListenAndServe(":9999", mainRouter) } 

I hope this helps someone.

+9
source

None of the previous answers helped me achieve exactly what I was looking for. I tried to use negroni.Wrap() around a Subrouter with lots of routes. I believe this is what the original poster wanted.

Additional context: I deploy to Google App Engine, thereby putting everything in the init() function.

 package hello import ( "fmt" "net/http" "github.com/codegangsta/negroni" "github.com/gorilla/mux" ) func init() { // Create the "root" router, if you will... r := mux.NewRouter().StrictSlash(true) // Create your "Subrouter" dedicated to /api which will use the PathPrefix apiRouter := mux.NewRouter().PathPrefix("/api").Subrouter().StrictSlash(true) // This step is where we connect our "root" router and our "Subrouter" together. r.PathPrefix("/api").Handler(negroni.New( negroni.HandlerFunc(myMiddleware), negroni.Wrap(apiRouter), )) // Define "root" routes using r r.HandleFunc(genHandleFunc("/", "root of site")) r.HandleFunc(genHandleFunc("/home", "home")) // Define "Subrouter" routes using apiRouter, prefix is /api apiRouter.HandleFunc(genHandleFunc("/", "root of API, /api")) // Matches: /api apiRouter.HandleFunc(genHandleFunc("/v1", "root of API V1, /api/v1")) // Matches: /api/v1 apiRouter.HandleFunc(genHandleFunc("/v1/resourceabc", "API V1 - resourceabc, /api/v1/resourceabc")) // Matches: /api/v1/resourceabc /* Finally we pass our "root" router to the net/http library. The "root" router will contain all of the routes for /api also. */ http.Handle("/", r) } // Silly function to quickly generate a HandleFunc func genHandleFunc(p string, msg string) (path string, f func(http.ResponseWriter, *http.Request)) { path = p f = func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "%v\n", msg) } return } func myMiddleware(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { fmt.Fprintln(w, "Before doing work...") next(w, r) fmt.Fprintln(w, "After doing work...") } 
+8
source

In any case, you would not use two routers.

Gorilla Mux has a Subrouter concept in which you define top-level domain properties on the main router, then use a Subrouter instance to map the individual paths.

For instance:

 mainRouter := mux.NewRouter() subRouter := mainRouter.PathPrefix("/").Subrouter() subRouter.HandleFunc("/test1", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "test1") }) subRouter.HandleFunc("/test2", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "test2") }) mainRouter.Handle("/", mainRouter) 

You can go even further than possible - for example, you might have another router in /test1 and a sub-processor that matches something even lower (say /test1/othertest ).

+5
source

Use full path in routines:

 router := mux.NewRouter() apiRoutes := mux.NewRouter() apiRoutes.Handle("/api/auth", Auth) router.PathPrefix("/api").Handler(negroni.New( Middleware1, Middleware2, negroni.Wrap(apiRoutes), )) 
+4
source

Source: https://habr.com/ru/post/973287/


All Articles