gorilla/mux 嵌套路由不匹配

gorilla/mux nested routes not matching

我不确定为什么我的路线没有被匹配。 localhost:8000 匹配,我得到了预期的输出但不是 localhost:8000/admin/test。当我尝试在浏览器上匹配 /admin/test 时,我得到 404

我想以这种方式组织我的代码,因为我想在每个 package.

中包含路由和其他子路由

项目结构

/admin
  admin.go
main.go

main.go

package main

import (
    "example.com/liondancer/playground/admin"
    "fmt"
    "github.com/gorilla/mux"
    "log"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there!")
}

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/", handler)
    r.PathPrefix("/admin").Handler(admin.NewHandler())
    log.Fatal(http.ListenAndServe(":8000", r))
}

admin.go

package admin

import (
    "fmt"
    "net/http"
    "github.com/gorilla/mux"
)

type Handler struct {
    router *mux.Router
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    h.router.ServeHTTP(w, r)
}

func NewHandler() *Handler {
    h := &Handler{}
    r := mux.NewRouter()
    h.router = r
    h.addRoutes()
    return h
}

func (h *Handler) addRoutes() {
    fmt.Print("hi here"). // <--- printed here to prove func gets ran.
    h.router.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        fmt.Fprintf(w, "test")
    })
}

我能够使用 Subrouter() 运行 这段代码。 这是 link 和 Subrouter() 用法示例

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/", handler)
    r.PathPrefix("/admin").Subrouter().HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        fmt.Fprintf(w, "test")
    })
    log.Fatal(http.ListenAndServe(":8000", r))
}

如果你想将它分离到另一个文件中,你也可以这样做:

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/", handler)
    subRoute := r.PathPrefix("/admin").Subrouter()
    NewHandler(subRoute)
    log.Fatal(http.ListenAndServe(":8000", r))
}

func NewHandler(r* mux.Router) *Handler {
    h := &Handler{}
    h.router = r
    h.AddRoutes()
    return h
}

func (h *Handler) AddRoutes() {
    fmt.Print("hi here") // <--- printed here to prove func gets ran.
        h.router.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        fmt.Fprintf(w, "test")
    })
}

您的嵌套处理程序永远不会匹配,因为您没有删除早期处理程序的 URL 前缀。 显示我的意思的快速修复:

// h.router.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {

// quick fix
h.router.HandleFunc("/admin/test", func(w http.ResponseWriter, r *http.Request) {

显然你希望你的嵌套处理程序不知道它是如何嵌套的,所以在注册子处理程序时,去除 URL 前缀,这样你的子处理程序将匹配:

// r.PathPrefix("/admin").Handler(admin.NewHandler())

// better
r.PathPrefix("/admin/").Handler(
    http.StripPrefix(
        "/admin",
        admin.NewHandler(),
    ),
)