在http.HandleFunc模式中的通配符

在Go(语言)中注册处理程序时,有什么方法可以在模式中指定通配符?

例如:

http.HandleFunc("/groups/*/people", peopleInGroupHandler) 

*可以是任何有效的URLstring。 或者是唯一的解决scheme来匹配/groups并从处理程序( peopleInGroupHandler )func中找出其余部分?

http.Handler和http.HandleFunc的模式不是正则expression式或globs。 没有办法指定通配符。 他们logging在这里 。

也就是说,创build自己的可以使用正则expression式或任何其他types的模式的处理程序并不难。 这是一个使用正则expression式(编译,但未经testing)的:

 type route struct { pattern *regexp.Regexp handler http.Handler } type RegexpHandler struct { routes []*route } func (h *RegexpHandler) Handler(pattern *regexp.Regexp, handler http.Handler) { h.routes = append(h.routes, &route{pattern, handler}) } func (h *RegexpHandler) HandleFunc(pattern *regexp.Regexp, handler func(http.ResponseWriter, *http.Request)) { h.routes = append(h.routes, &route{pattern, http.HandlerFunc(handler)}) } func (h *RegexpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { for _, route := range h.routes { if route.pattern.MatchString(r.URL.Path) { route.handler.ServeHTTP(w, r) return } } // no pattern matched; send 404 response http.NotFound(w, r) } 

自2011年以来,您现在可以(2014+)find其他解决scheme。
例如, Gorilla Web工具包的mux包提供了所有types的路由选项:

  • 请求path上的模式匹配,带有可选的正则expression式。
  • 匹配URL主机和scheme,请求方法,头和查询值。
  • 基于自定义function进行匹配。
  • 使用子路由器进行简单的嵌套路由。

它可以很容易地集成到任何BYOR(带自己的路由器)http库, 像negroni 。

这里是一个例子,从文章“ 大猩猩VS帕特与路线:复式摊牌 ”:

 package main import ( "github.com/gorilla/mux" "log" "net/http" ) func main() { rtr := mux.NewRouter() rtr.HandleFunc("/user/{name:[az]+}/profile", profile).Methods("GET") http.Handle("/", rtr) log.Println("Listening...") http.ListenAndServe(":3000", nil) } func profile(w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) name := params["name"] w.Write([]byte("Hello " + name)) } 

有时候最好不要再使用另一个“魔术”软件包,而要理解底层的情况

在这种情况下,“魔法”在“ gorilla/mux/regexp.go ”中定义,并在此处进行testing 。
这个想法是提取命名variables,组装一个匹配的正则expression式,创build一个“反向”模板来构buildURL并编译正则expression式来validationURL构build中使用的variables值。

我只是想添加julienschmidt/httprouter女巫就像net/http海狸,但有一个额外的参数为url值和支持的请求方法:

https://github.com/julienschmidt/httprouter

 package main import ( "fmt" "github.com/julienschmidt/httprouter" "net/http" "log" ) func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { fmt.Fprint(w, "Welcome!\n") } func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) } func main() { router := httprouter.New() router.GET("/", Index) router.GET("/hello/:name", Hello) log.Fatal(http.ListenAndServe(":8080", router)) } 

它似乎比大猩猩多路复用器(根据github)稍微更受欢迎,它也声称需要更less的内存。

https://github.com/julienschmidt/go-http-routing-benchmark

你可以检查violetear如何处理dynamic+ catchall(通配符)模式,这只是为了补充,例如:

 uuid := `[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}` router.AddRegex(":uuid") router.HandleFunc("/test/:uuid/:uuid", handleUUID, "GET,HEAD") 

在这种情况下,请求可能有2个不同的UUIDS

对于dynamic/通配符,这可能适用于:

 http://api.violetear.org/command/ping/127.0.0.1 \______/\___/\________/ | | | static | dynamic 

正则expression式可以用来匹配IP:

 router.AddRegex(":ip", `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`) router.HandleFunc("/command/ping/:ip", ipHandler, "GET") 

或者只是一个只允许GETHEAD方法的catch:

 router.HandleFunc("/command/ping/*", anyHandler, "GET, HEAD") 

更多的例子可以在这里find: https : //violetear.org/post/how-it-works/

Beego,所有Golangnetworking服务器问题的答案。 Wetalk是一个build立在Beego上的博客网站。