在Blake Mizerany的Golang演讲的this Youtube视频(大约15:29)中,他谈到了如何在不使用第三方软件包的情况下构建路由器,详细介绍了如何构建路由有一个可变组件,例如id。这是他使用的处理程序,第一行显示如何获取路径的变量组件(即键)
func productHandler(w http.ResponseWriter, r *http.Request){
key := r.URL.Path[len("/products/":]
switch r.Method{
case "GET":
//do stuff
case "POST"
//do stuff
default:
http.Error(w, "method not allowed", 405)
}
}
虽然他的实际路线是什么样的,但从他的演讲中并不清楚。
我正在尝试构建一个处理带有id的put请求的路由。当我单击页面上的元素时,它会向此路径发送一个put请求
http://localhost:8080/products/1433255183951
我有这样的路线
http.HandleFunc("/products/{id}", doSomethingWithProduct){
}
当然还有func
func doSomethingWithProduct(res http.ResponseWriter, req *http.Request{
key := req.URL.Path[len("/products/"):]
log.Println(key, "is this logging?? nope")
}
问题。即使我设置了这个路由,还有处理程序,当我单击该元素时,我找不到404,并且没有迹象表明我的函数被调用(即它没有记录)
问题:如何创建处理PUT请求的自定义路由/功能
http://localhost:8080/products/1433255183951
答案 0 :(得分:3)
HandleFunc
不知道如何处理{id}
。给它一个可以匹配的特定路径:
http.HandleFunc("/products/", doSomethingWithProduct)
答案 1 :(得分:3)
http.HandleFunc
不会像您尝试使用{id}
那样处理“捕获群组”。
http.HandleFunc("/products/", handler)
将匹配以此模式开头的所有路由。你必须自己解析剩下的部分。
请参阅ServeMux。
ServeMux是一个HTTP请求多路复用器。它将每个传入请求的URL与已注册模式的列表进行匹配,并调用与该URL最匹配的模式的处理程序。
模式名称是固定的,有根的路径,如“/favicon.ico”,或有根的子树,如“/ images /”(请注意尾部斜杠)。较长的模式优先于较短的模式,因此如果存在为“/ images /”和“/ images / thumbnails /”注册的处理程序,则后面的处理程序将被调用以“/ images / thumbnails /”开头的路径和前者将收到“/ images /”子树中任何其他路径的请求。
请注意,由于以斜杠结尾的模式命名为带根子树,因此模式“/”匹配所有与其他已注册模式不匹配的路径,而不仅仅是带有Path ==“/".
的URL模式可以选择以主机名开头,仅限制与该主机上的URL匹配。特定于主机的模式优先于一般模式,因此处理程序可以注册两个模式“/ codesearch”和“codesearch.google.com/”,而不会接管“http://www.google.com/”的请求。
ServeMux还负责清理URL请求路径,重定向包含的任何请求。或..元素到等效的.-和..-免费URL。
答案 2 :(得分:3)
内置的HTTP路由器不像绑定参数那样做任何事情;但是,您可以指定整个前缀以与处理程序关联。请参阅http.ServeMux
的文档。
尝试这样的事情:
func main() {
productsPrefix := "/products/"
http.HandleFunc(productsPrefix, func(w http.ResponseWriter, r *http.Request) {
if (r.Method == "PUT") && (strings.Index(r.URL.Path, productsPrefix) == 0) {
productId := r.URL.Path[len(productsPrefix):]
fmt.Printf("OK: %s %s productId=%s\n", r.Method, r.URL.Path, productId)
}
})
log.Print("Listening on localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
例如:
$ curl -XPUT http://localhost:8080/products/1234
# => OK: PUT /products/1234 productId=1234