使用下面的代码,当我访问/ test2时,它以404响应 - 未找到。 / test1正常工作。这是为什么?尽管路由器实现了http.Handler接口,但是不允许嵌套吗?
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)
}
修改
我的主要目标是添加一些初始工作,这些工作对于subRouter中的所有路由都是常见的,并且仅适用于它们。更具体地说,我想使用Negroni作为我的中间件orchiestrator。 在Negroni网站上有一个将中间件添加到路由组的示例:
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基本上执行每个参数的ServeHTTP方法,因为它们都实现了http.Handler。它按顺序执行它们,因此路由器路由将是最后一个。
我熟悉Mux中Subrouter
的概念,但AFAIK我不能像上面的例子那样使用它,特别是我不能在两者之间注入任何东西mainRouter及其Subrouter
。这就是嵌套看起来更灵活的原因。
答案 0 :(得分:9)
我知道这个问题有些陈旧,但我花了一些时间来弄清楚处理程序和匹配工作的进展情况。您可以看到我的实验代码here。
基本上,您可以使用以下代码获得所需的效果:
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)
}
我希望这有助于某人。
答案 1 :(得分:8)
之前给出的答案都没有帮助我实现我正在寻求的目标。我试图在negroni.Wrap()
周围使用Subrouter
并且有很多路线。我相信这就是原版海报所需要的。
附加上下文:我正在Google App Engine上部署,因此将所有内容都放在init()
函数中。
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...")
}
答案 2 :(得分:5)
无论如何你不会在这里使用两个路由器。
Gorilla Mux具有Subrouter
的概念,您可以在主路由器上定义顶级域属性,然后使用Subrouter
实例映射各个路径。
例如:
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)
你可以走得更远 - 例如,你可以在/test1
使用另一个路由器,并且子路由器可以与下面的任何路由器匹配(比如说/test1/othertest
)。
答案 3 :(得分:4)
在子路径中使用完整路径:
router := mux.NewRouter()
apiRoutes := mux.NewRouter()
apiRoutes.Handle("/api/auth", Auth)
router.PathPrefix("/api").Handler(negroni.New(
Middleware1,
Middleware2,
negroni.Wrap(apiRoutes),
))