go - 防止为所有不匹配的请求调用 http.handleFunc ("/", func(w, r) { }) 处理程序

标签 go

考虑下面非常基本的 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

最佳答案

http.ServeMux documentation说:

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/

相关文章:

multithreading - 如何等待一组 goroutines 中的*任何*发出信号而不需要我们等待它们这样做

Golang 错误处理

struct - 如何从函数访问结构的实例字段?

math - golang 中模拟钟形曲线上的值

在 Go 中解析 YAML : map in list

go - Memcached Kubernetes 客户端 Golang

arrays - 在 Go 中使用 slice 进行子集检查

gdb - 如何使用 GDB 正确调试 `go test -c` 生成的二进制文件?

postgresql - Gorm 无法连接到本地 postgres 数据库

json - 得到 : Cannot unmarshal string into Go value