嵌套的Gorilla Mux路由器不起作用

时间:2014-08-03 18:26:25

标签: go mux gorilla

使用下面的代码,当我访问/ 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。这就是嵌套看起来更灵活的原因。

4 个答案:

答案 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),
))