http.ServeMux route mounting?

huangapple go评论92阅读模式
英文:

http.ServeMux route mounting?

问题

让我们来看一下以下的代码模式:

package main

import (
	"fmt"
	"net/http"
)

func main() {
	admin := http.NewServeMux()
	admin.HandleFunc("/", root)
	admin.HandleFunc("/foo", foo)
	http.Handle("/admin", admin)
	http.ListenAndServe(":4567", nil)
}

func root(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Admin: ROOT")
}

func foo(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Admin: FOO")
}

当我运行/admin时,为什么它会触发root处理程序,但当我运行/admin/foo时却不会触发呢?只是为了明确,我不是在寻找替代的包,我实际上有一个自定义的路由器,我只是对这里发生的事情感到好奇,因为这个模式对我来说并不太合理。

英文:

Let's take the following pattern:

package main

import (
	"fmt"
	"net/http"
)

func main() {
	admin := http.NewServeMux()
	admin.HandleFunc("/", root)
	admin.HandleFunc("/foo", foo)
	http.Handle("/admin", admin)
	http.ListenAndServe(":4567", nil)
}

func root(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Admin: ROOT")
}

func foo(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Admin: FOO")
}

How is it that when I run /admin, it will fire the root handler, but when I run /admin/foo it won't? Just to be clear, I'm not looking for an alternative package, I actually have a custom router, I'm just generally curious to what's going on here as this pattern isn't making much sense to me.

答案1

得分: 1

像@DewyBroto所说的那样,在子mux中你必须使用完整的路径。

你可以创建一个类似这样的包装器:

func NewChildMux(prefix string, vars ...interface{}) *http.ServeMux {
    sm := http.NewServeMux()
    for i := 0; i < len(vars); i += 2 {
        path := prefix + vars[i].(string)
        sm.HandleFunc(path, vars[i+1].(func(http.ResponseWriter, *http.Request)))
    }
    return sm
}

func main() {
    admin := NewChildMux("/admin",
        "/", root,
        "/foo/", foo,
    )
    http.Handle("/admin/", admin)
    http.ListenAndServe(":4567", nil)
}
英文:

Like @DewyBroto said, you have to use the full path in the child mux.

You could make a wrapper like this:

func NewChildMux(prefix string, vars ...interface{}) *http.ServeMux {
	sm := http.NewServeMux()
	for i := 0; i &lt; len(vars); i += 2 {
		path := prefix + vars[i].(string)
		sm.HandleFunc(path, vars[i+1].(func(http.ResponseWriter, *http.Request)))
	}
	return sm
}

func main() {
	admin := NewChildMux(&quot;/admin&quot;,
		&quot;/&quot;, root,
		&quot;/foo/&quot;, foo,
	)
	http.Handle(&quot;/admin/&quot;, admin)
	http.ListenAndServe(&quot;:4567&quot;, nil)
}

答案2

得分: 1

请尝试以下代码:

func main() {
    admin := http.NewServeMux()

    // 使用挂载点作为所有路径的前缀。即使从另一个 ServeMux 调用,ServeMux 也会匹配完整路径。
    mountPoint := "/admin"
    admin.HandleFunc(mountPoint, root)
    admin.HandleFunc(mountPoint + "/foo", foo)

    // 在挂载点后添加斜杠以指示子树匹配。
    http.Handle(mountPoint + "/", admin)

    http.ListenAndServe(":4567", nil)
}

这段代码是一个简单的 Go 语言示例,用于创建一个 HTTP 服务器。它使用了 http 包中的 ServeMux 类型来处理不同的请求路径。在这个示例中,我们创建了一个名为 adminServeMux 实例,并将其挂载在 /admin 路径下。然后,我们使用 HandleFunc 方法将处理函数与路径关联起来。最后,我们使用 ListenAndServe 方法启动服务器并监听端口 4567

英文:

Try the following:

func main() {
    admin := http.NewServeMux()

    // Prefix all paths with the mount point. A ServeMux matches
    // the full path, even when invoked from another ServeMux.
    mountPoint := &quot;/admin&quot;
    admin.HandleFunc(mountPoint, root)
    admin.HandleFunc(mountPoint + &quot;/foo&quot;, foo)

    // Add a trailing &quot;/&quot; to the mount point to indicate a subtree match.
    http.Handle(mountPoint + &quot;/&quot;, admin)

    http.ListenAndServe(&quot;:4567&quot;, nil)
}

huangapple
  • 本文由 发表于 2014年9月16日 01:10:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/25853257.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定