Go 防止为所有不匹配的请求调用http.handleFunc(“/”,func(w,r){})处理程序
考虑以下非常基本的HTTP服务器代码,该代码在main函数中通过使用参数调用run启动,其中该参数用于指定根目录路径 包干管 进口fmt 导入net/http 导入字符串 func main{ //运行///选项1 //运行/newbase//选项2 } func runbasePath字符串{ var path=fmt.Sprintf%s,basePath if!strings.hasprofixpath,/{ 路径=fmt.Sprintf/%s,路径 } if!strings.HasSuffixpath,/{ path=fmt.Sprintf%s/,路径 } http.handleFuntfmt.Sprintf%sfoo,路径,handleFoo http.handleFuntfmt.Sprintf%sbar,路径,把手 http.handleFuntfmt.Sprintf%s,路径,handleRoot http.listendserve:60001,无 } func handleRootw http.ResponseWriter,r*http.Request{ fmt.Fprintw,根 } func handleFoow http.ResponseWriter,r*http.Request{ fmt.Fprintw,Foo } func handleBarw http.ResponseWriter,r*http.Request{ fmt.Fprintw,巴 } 如果调用run/,服务器应该响应url/、/foo和/bar 如果调用run/newbase,服务器应该响应URL/newbase/、/newbase/foo和/newbase/bar 我希望任何其他URL返回标准HTTP/404,但似乎为未处理的子路径调用了/handler。这会导致行为上的奇怪差异,其中:Go 防止为所有不匹配的请求调用http.handleFunc(“/”,func(w,r){})处理程序,go,Go,考虑以下非常基本的HTTP服务器代码,该代码在main函数中通过使用参数调用run启动,其中该参数用于指定根目录路径 包干管 进口fmt 导入net/http 导入字符串 func main{ //运行///选项1 //运行/newbase//选项2 } func runbasePath字符串{ var path=fmt.Sprintf%s,basePath if!strings.hasprofixpath,/{ 路径=fmt.Sprintf/%s,路径 } if!strings.HasSuff
| 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提供/handler服务,而是使用默认的HTTP/404响应
# go version
go version go1.14.9 linux/amd64
报告说:
模式名称固定的根路径,如/favicon.ico,或根子树,如/images/注意尾部的斜杠
及
请注意,由于以斜杠结尾的模式命名一个根子树,因此pattern/匹配其他注册模式不匹配的所有路径,而不仅仅是Path=/的URL
要处理与/或以/结尾的任何其他模式的精确匹配,请向处理程序添加代码,如果路径不等于该模式,则以404响应。用于使用默认的404响应进行响应
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
// code to handle / here
})
报告说:
模式名称固定的根路径,如/favicon.ico,或根子树,如/images/注意尾部的斜杠
及
请注意,由于以斜杠结尾的模式命名一个根子树,因此pattern/匹配其他注册模式不匹配的所有路径,而不仅仅是Path=/的URL
要处理与/或以/结尾的任何其他模式的精确匹配,请向处理程序添加代码,如果路径不等于该模式,则以404响应。用于使用默认的404响应进行响应
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
// code to handle / here
})
发生这种情况的原因是没有基于前缀的匹配
以斜杠结尾的模式命名根子树,模式/匹配其他注册模式不匹配的所有路径,而不仅仅是路径为==/的URL
所以,如果您想要一个精确的基于路径的匹配,实现您的目标的一个方法是更改此部分
http.HandleFunc(fmt.Sprintf("%sfoo", path), handleFoo)
http.HandleFunc(fmt.Sprintf("%sbar", path), handleBar)
http.HandleFunc(fmt.Sprintf("%s", path), handleRoot)
为此:
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
switch r.URL.Path {
case fmt.Sprintf("%sfoo", path):
handleFoo(w, r)
case fmt.Sprintf("%sbar", path):
handleBar(w, r)
case fmt.Sprintf("%s", path):
handleRoot(w, r)
default:
http.NotFoundHandler().ServeHTTP(w, r)
}
})
发生这种情况的原因是没有基于前缀的匹配
以斜杠结尾的模式命名根子树,模式/匹配其他注册模式不匹配的所有路径,而不仅仅是路径为==/的URL
所以,如果您想要一个精确的基于路径的匹配,实现您的目标的一个方法是更改此部分
http.HandleFunc(fmt.Sprintf("%sfoo", path), handleFoo)
http.HandleFunc(fmt.Sprintf("%sbar", path), handleBar)
http.HandleFunc(fmt.Sprintf("%s", path), handleRoot)
为此:
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
switch r.URL.Path {
case fmt.Sprintf("%sfoo", path):
handleFoo(w, r)
case fmt.Sprintf("%sbar", path):
handleBar(w, r)
case fmt.Sprintf("%s", path):
handleRoot(w, r)
default:
http.NotFoundHandler().ServeHTTP(w, r)
}
})
由于%sfoo和%sbar不以/结尾,因此在第一个代码段中注册单独的处理程序与在第二个代码段中比较路径(性能除外)之间没有区别。因为%sfoo和%sbar不以/结尾,在第一个代码段中注册单独的处理程序与在第二个代码段中比较路径(性能除外)之间没有区别。