gorilla / mux

Package gorilla/mux is a powerful HTTP router and URL matcher for building Go web servers with 🦍
https://gorilla.github.io
BSD 3-Clause "New" or "Revised" License
20.89k stars 1.85k forks source link

mux.Vars is empty - and shoudn't be #84

Closed tcurdt closed 9 years ago

tcurdt commented 9 years ago

I bet it's just me doing something wrong - but then I would ask to improve the docs. Here is what I am trying:

router := mux.NewRouter()
http.Handle("/", handler.LoggingInterceptor(handler.AuthenticationInterceptor(router)))
router.HandleFunc("/project/{project:[0-9a-zA-Z]+}", handler.PutProject).Methods("PUT")

With the interceptors along the lines of:

func AuthenticationInterceptor(router http.Handler) http.Handler {
  return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
    vars := mux.Vars(req)
    glog.Infof("Vars: [%q] but %s", vars, req.URL.Path)
    router.ServeHTTP(res, req)
  })
}

and

func LoggingInterceptor(router http.Handler) http.Handler {
  return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
    router.ServeHTTP(res, req)
  })
}

Pretty straight forward. But somehow the variables are empty inside the interceptor.

Vars: [map[]] but /project/test

As you can see from the logs the request does get matched correctly and the request uri looks OK - but there is no var "project".

What am I missing here?

kisielk commented 9 years ago

Your interceptor is calling mux.Vars before it calls the router, so the router code which extracts the route vars hasn't run yet.

tcurdt commented 9 years ago

Ahhhhhhhh!

Not sure there is a suggested way of handling such things but simple chaining did the trick for me:

router.HandleFunc("/feedback/{project:[0-9a-zA-Z]+}", handler.Test(handler.PutProject)).Methods("PUT")

And then I can either call the callback to pass it on in the chain or handle it myself

func Test(router http.HandlerFunc) http.HandlerFunc {
  return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {

    vars := mux.Vars(req)
    glog.Infof("Vars: [%q]", vars)

    router(res, req)
  })
}