考虑下面非常基本的 HTTP 服务器代码,通过使用参数调用 run()
在 main()
函数中启动,其中参数旨在指定一个根目录路径。
package main
import "fmt"
import "net/http"
import "strings"
func main() {
// run("/") // option 1
// run("/newbase") // option 2
}
func run(basePath string) {
var path = fmt.Sprintf("%s", basePath)
if !strings.HasPrefix(path, "/") {
path = fmt.Sprintf("/%s", path)
}
if !strings.HasSuffix(path, "/") {
path = fmt.Sprintf("%s/", path)
}
http.HandleFunc(fmt.Sprintf("%sfoo", path), handleFoo)
http.HandleFunc(fmt.Sprintf("%sbar", path), handleBar)
http.HandleFunc(fmt.Sprintf("%s", path), handleRoot)
http.ListenAndServe(":60001", nil)
}
func handleRoot(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Root")
}
func handleFoo(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Foo")
}
func handleBar(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Bar")
}
如果调用 run("/")
,服务器应响应 URL /、/foo 和 /酒吧。
如果调用 run("/newbase")
,服务器应响应 URL /newbase/、/newbase/foo和/newbase/bar。
我希望任何其他 URL 返回标准 HTTP/404,但似乎为未处理的子路径调用了 / 处理程序。这会导致行为上出现奇怪的差异:
| For run("/") | For run("/newbase")
Entered URL |---------------------------------+---------------------------------
| Desired | Actual | Desired | Actual
------------------+----------------+----------------+----------------+----------------
/ | HTTP/200 Root | HTTP/200 Root | HTTP/404 | HTTP/404
------------------+----------------+----------------+----------------+----------------
/foo | HTTP/200 Foo | HTTP/200 Foo | HTTP/404 | HTTP/404
------------------+----------------+----------------+----------------+----------------
/foo/qux | HTTP/404 | HTTP/200 Root | HTTP/404 | HTTP/404
------------------+----------------+----------------+----------------+----------------
/bar | HTTP/200 Bar | HTTP/200 Bar | HTTP/404 | HTTP/404
------------------+----------------+----------------+----------------+----------------
/baz | HTTP/404 | HTTP/200 Root | HTTP/404 | HTTP/404
------------------+----------------+----------------+----------------+----------------
/newbase | HTTP/404 | HTTP/200 Root | HTTP/200 Root | HTTP/200 Root
------------------+----------------+----------------+----------------+----------------
/newbase/foo | HTTP/404 | HTTP/200 Root | HTTP/200 Foo | HTTP/200 Foo
------------------+----------------+----------------+----------------+----------------
/newbase/foo/qux | HTTP/404 | HTTP/200 Root | HTTP/404 | HTTP/200 Root
------------------+----------------+----------------+----------------+----------------
/newbase/bar | HTTP/404 | HTTP/200 Root | HTTP/200 Bar | HTTP/200 Bar
------------------+----------------+----------------+----------------+----------------
/newbase/baz | HTTP/404 | HTTP/200 Root | HTTP/404 | HTTP/200 Root
我认为发生这种情况是因为 http.HandleFunc
的第一个参数被视为最接近匹配的模式,而不是精确匹配。
是否有任何方法可以强制处理程序要求精确(最好不区分大小写)匹配,以便它不会为未注册 URL 的 / 处理程序提供服务,而是使用默认 HTTP 进行响应/404?
# go version
go version go1.14.9 linux/amd64
最佳答案
Patterns name fixed, rooted paths, like "/favicon.ico", or rooted subtrees, like "/images/" (note the trailing slash).
和
Note that since a pattern ending in a slash names a rooted subtree, the pattern "/" matches all paths not matched by other registered patterns, not just the URL with Path == "/".
要处理 /
(或以 /
结尾的任何其他模式)上的精确匹配,请将代码添加到处理程序,以便在路径不等于时响应 404模式。使用http.NotFound以“默认”404 响应进行响应。
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
// code to handle / here
})
关于go - 防止为所有不匹配的请求调用 http.handleFunc ("/", func(w, r) { }) 处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64437991/