Problem nesting gorilla/mux routers

643 views
Skip to first unread message

Lee Hambley

unread,
Dec 11, 2014, 8:34:51 AM12/11/14
to goril...@googlegroups.com
First of all, I've seen the thread "Is it possible to nest Mux routers?", and unfortunately as the OP was so tied to Negroni no solution was posted, although I did take onboard some of the debugging tips.

I'm trying to do something like this, the contrived example is:

package main
import (
"fmt"
"net/http"
)
func NewUserRouter() *mux.Router {
userRouter := mux.NewRouter()
userRouter.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Users Index\n")
})
userRouter.HandleFunc("/show/{uuid}", func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Users Show\n")
})
return userRouter
}
func NewOtherRouter() *mux.Router {
otherRouter := mux.NewRouter()
otherRouter.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "Other Index\n")
})
return otherRouter
}
func main() {
// Compose Routers
r := mux.NewRouter()
r.Path("/users").Handler(NewUserRouter())
r.Path("/other").Handler(NewOtherRouter())
// Run
http.ListenAndServe(":3001", r)
}

(Also at http://play.golang.org/p/s3gFqovlmF, incase the formatting here is off, but it won't run due to depending on `gorilla/mux`).

This isn't the first thing I've tried, I've also played around unsuccessfully with `Path().Handler()` and `SubRouter()`, but to no avail, also with more liberal regular expressions, e.g. `r.Path("/users.*").Handler(NewUserRouter())`

I think it goes without saying, that the behaviour I'm expecting is to be able to do the following, with the following output:

$ curl localhost:3001/users
=> "Users Index"
$ curl localhost:3001/users/show/foo
=> "Users Show"
$ curl localhost:3001/other
=> "Other Index"

I made the following change to `gorilla/mux` to print some kind of debugging information, but it's not terribly helpful:

diff --git a/route.go b/route.go
index c310e66..8512b50 100644
--- a/route.go
+++ b/route.go
@@ -35,12 +35,16 @@ type Route struct {
 
 // Match matches the route against the request.
 func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
+
+ fmt.Printf("gorilla/mux Route.Match():\n\tRequest URL: %s\n", req.URL)
+
  if r.buildOnly || r.err != nil {
  return false
  }
  // Match everything.
  for _, m := range r.matchers {
  if matched := m.Match(req, match); !matched {
+ fmt.Printf("\tNot matched: %s\n", m)
  return false
  }
  }

It prints something like the following:

gorilla/mux Route.Match():
        Request URL: /users
        Not matched: &{/users %!s(bool=false) %!s(bool=false) %!s(bool=false) %!s(*regexp.Regexp=&{^/users$ 0xc208038b10 0xc208038b70 /users [47 117 115 101 114 115] false 47 8 4 0 [] false {0 0} [0xc208062600]}) /users [] []}
gorilla/mux Route.Match():
        Request URL: /users
        Not matched: &{/other %!s(bool=false) %!s(bool=false) %!s(bool=false) %!s(*regexp.Regexp=&{^/other$ 0xc208038e40 0xc208038ea0 /other [47 111 116 104 101 114] false 47 8 4 0 [] false {0 0} [0xc208062700]}) /other [] []}

(For simple curl requests to `curl localhost:3001/users`). 

I wonder if someone can please bump me in the correct direction?

Lee Hambley

unread,
Dec 12, 2014, 9:46:30 AM12/12/14
to goril...@googlegroups.com
Having continued to play around, I stumbled upon this thread at Github, that helped. Having changed my main to:

func main() {
// Compose Routers
r := mux.NewRouter().StrictSlash(true)
AddUserRouter(r.PathPrefix("/users").Subrouter())
AddNewOtherRouter(r.PathPrefix("/other").Subrouter())
// Gracefully Run
http.ListenAndServe(":3001", r)
}

The code is working perfectly. I also removed the `return` from the functions which is unnecessary as we're passing a pointer around.
Reply all
Reply to author
Forward
0 new messages