当使用嵌套的http.ServeMux定义服务器的端点时,我遇到了这样的问题:处理程序总是以"301永久移动“来响应任何请求,即使URL路径应该匹配。
示例:
package main
import "net/http"
func main() {
api := http.NewServeMux()
api.HandleFunc("ping", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("pong\n"))
})
root := http.NewServeMux()
root.Handle("/api/", http.StripPrefix("/api/", api))
http.ListenAndServe(":8080", root)
}当试图访问/api/ping时,服务器重定向到/ping (当然返回404 )。同样的情况也发生在/api/ - /api/foo重定向到/foo的任何路由上。
我用的是围棋1.13和卷曲7.58。
发布于 2020-02-21 21:42:02
编辑:为了简化在火狐中的测试,我禁用了缓存。否则,我将不得不手动清除缓存,以获得准确的结果。不过,我在使用Chrome时似乎没有同样的问题。

记住我是新来的但这件事把我逼疯了..。我正经历着和你一样的行为(很明显)。
看来,Go/http对模式的格式化方式很挑剔。
我花了大约一个小时来处理这个问题,最后使用以下代码获得了一个工作示例:
// Working Code
package main
import "net/http"
func main() {
root := http.NewServeMux()
api := http.NewServeMux()
api.HandleFunc("/ping", myHandlerFunc)
root.Handle("/api/", http.StripPrefix("/api", api))
http.ListenAndServe(":8080", root)
}
func myHandlerFunc(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("pong\n"))
}我尝试了尽可能多的不同配置(就/正斜杠而言),而上面的代码是我让它工作的唯一方法。
特别提到:
// Leading forward slash on /ping
api.HandleFunc("/ping", myHandlerFunc)
// The first /api/ is surrounded in forward slashes,
// the second /api only contains a leading forward slash
root.Handle("/api/", http.StripPrefix("/api", api))将代码更改为这个会导致404.
// DOES NOT WORK!!
package main
import "net/http"
func main() {
root := http.NewServeMux()
api := http.NewServeMux()
api.HandleFunc("/ping", myHandlerFunc)
root.Handle("/api", http.StripPrefix("/api", api))
http.ListenAndServe(":8080", root)
}
func myHandlerFunc(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("pong\n"))
}我希望这在某种程度上有帮助!干杯
发布于 2020-02-21 22:24:46
前几天我只是在处理这个问题。我认为ServeMux需要有根的树(从/开始),或者它将路径解释为主机名。
模式命名固定的根路径,如"/favicon.ico",或根子树,如“/图像/”.模式可以选择以主机名开头,仅将匹配限制在该主机上。
我推测ping被解释为主机名,它在servemux的操作方式上造成了奇怪。
在人们编写的其他解决方案中,他们改变了/的位置,因此ping路径最终成为/ping。
就我个人而言,我不喜欢在一个地方写/api/,在另一个地方写/api。在我的特殊情况下,我决定使用这样的方法:
root.Handle(createAPIEndpoints("/api/"))
...
func createAPIEndpoints(base string) (string, *http.ServeMux) {
mux := http.NewServeMux()
mux.HandleFunc(base+"ping", func(...){...})
mux.HandleFunc(base+"another", func(...){...})
// another buried servemux
mux.Handle(createMoreEndpoints(base+"more/"))
return base, mux
}但是,如果您想用处理程序包装处理程序(比如使用StripPrefix或其他类型的中间件),由于返回了2个值,这就不能很好地工作。
发布于 2021-03-11 09:32:42
我遇到了一个类似的问题,但只在尝试在嵌套路由器下定义根路径/的情况下。
为了处理它,我重写了自己的stripPefix()方法如下:
package main
import "net/http"
func main() {
root := http.NewServeMux()
api := http.NewServeMux()
api.HandleFunc("/", myHandlerFunc)
root.Handle("/api", stripPrefix("/api", api))
http.ListenAndServe(":8080", root)
}
func myHandlerFunc(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK\n"))
}
// Modified version of http.StripPrefix()
func stripPrefix(prefix string, h http.Handler) http.Handler {
if prefix == "" {
return h
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if p := strings.TrimPrefix(r.URL.Path, prefix); len(p) < len(r.URL.Path) {
r2 := new(http.Request)
*r2 = *r
r2.URL = new(url.URL)
*r2.URL = *r.URL
if len(p) == 0 {
r2.URL.Path = "/"
} else {
r2.URL.Path = p
}
h.ServeHTTP(w, r2)
} else {
http.NotFound(w, r)
}
})
}https://stackoverflow.com/questions/60344955
复制相似问题