英文:
PathPrefixed Subrouter with individual handlers
问题
给定以下代码(完整示例请参见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)
我本来期望以下URL将触发相应的处理程序,但似乎无法使其工作:
- ✔ POST /widgets => h.Create
- ✔ GET /widgets/123 => h.Show (假设 PathPrefix('/{uuid}'))
- ✔ GET /widgets/123/ => h.Show (如果有 'PathPrefix('/{uuid}/')' 则需要)
- ✖ GET /widgets/123/foos => h.Foos (实际上路由到了 h.Show)
- ✖ GET /widgets/123/bars => h.Bars (实际上路由到了 h.Show)
不幸的是,最后两个URL似乎都无法路由,它们都触发了 h.Show
。有人能指出我做错了什么吗?我本来期望一个没有尾部斜杠的无界限 {uuid}
可以忽略 /
继续运行,但事实并非如此。
我甚至不知道这是否与 Subrouter 的 strict-slash 问题有关,该问题在 Github 上仍然未解决(#31),但据我所了解,我尝试了其中的替代方法(即 object.Methods("GET").Path("/").Handler(h.Show)
)。
通过 Methods()
在 object
根上挂载的处理程序是否会阻止任何进一步匹配的路由?
英文:
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?
答案1
得分: 2
问题在于gorilla/mux
会触发第一个匹配的处理程序。这一点非常重要,因为它会匹配到第一个匹配的处理程序。
这意味着逻辑上位于 /{id}/
下的路由永远不会被找到,因为匹配它们的路由会首先被父处理程序匹配到。
将代码更改为以下内容可以按预期工作:
// 集合
root := r.PathPrefix("/widgets/").Subrouter()
object := root.PathPrefix("/{uuid}").Subrouter()
// 关系
object.Methods("GET").Path("/foos").Handler(eh.Foos)
object.Methods("GET").Path("/bars").Handler(eh.Bars)
// 单个
root.Methods("POST").Handler(h.Create)
object.Methods("GET").Handler(h.Show)
object.Methods("PUT").Handler(h.Replace)
object.Methods("DELETE").Handler(h.Delete)
然后一切都可以正常工作。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论