Given the following (complete example at Go playground):
// Collection
root := r.PathPrefix("/widgets/").Subrouter()
root.Methods("POST").Handler(h.Create)
// Individual
object := root.PathPrefix("/{uuid}").Subrouter()
// ~neither: object := root.PathPrefix("/{uuid}").Subrouter()
object.Methods("GET").Handler(h.Show)
object.Methods("PUT").Handler(h.Replace)
object.Methods("DELETE").Handler(h.Delete)
// Relationships
object.Methods("GET").Path("/foos").Handler(eh.Foos)
object.Methods("GET").Path("/bars").Handler(eh.Bars)
I would have expected the following URLs to trigger the respective handlers, but I can't seem to make it work:
✔ POST /widgets => h.Create
✔ GET /widgets/123 => h.Show (assumes PathPrefix('/{uuid}'))
✔ GET /widgets/123/ => h.Show (required if 'PathPrefix('/{uuid}/')')
✖ GET /widgets/123/foos => h.Foos (actually routes h.Show)
✖ GET /widgets/123/bars => h.Bars (actually routes h.Show)
Unfortunately neither of the last two are apparently routable, they both trigger h.Show
, can anyone point out what I'm doing wrong? I might have expected that having an unbounded {uuid}
(without the trailing slash) could have run-on, ignoring the /
but that doesn't seem to be the case.
I don't even know if this has to do with the Subrouter strict-slash issue which is still open on Github (#31), but to the best of my understanding I did try the alternatives there. (i.e object.Methods("GET").Path("/").Handler(h.Show)
)
Could the Handler mounted on the object
root via Methods()
prevent any further routes matching?
The problem was that gorilla/mux
fires the first matching handler. That's important the first matching handler.
That means that routes logically under /{id}/
are never found, since the routes that would match them are matched first by the parent handler.
Changing the code to the following makes it work as expected:
// Collection
root := r.PathPrefix("/widgets/").Subrouter()
object := root.PathPrefix("/{uuid}").Subrouter()
// Relationships
object.Methods("GET").Path("/foos").Handler(eh.Foos)
object.Methods("GET").Path("/bars").Handler(eh.Bars)
// Individual
root.Methods("POST").Handler(h.Create)
object.Methods("GET").Handler(h.Show)
object.Methods("PUT").Handler(h.Replace)
object.Methods("DELETE").Handler(h.Delete)
Then things work perfectly.