http.HandleFunc模式中的通配符

Mat*_*yer 65 regex go

在Go(语言)中注册处理程序时,有没有办法在模式中指定通配符?

例如:

http.HandleFunc("/groups/*/people", peopleInGroupHandler)
Run Code Online (Sandbox Code Playgroud)

其中*可以是任何有效的URL字符串.或者是唯一的解决方案匹配/groups并从handler(peopleInGroupHandler)func中计算出其余部分?

Eva*_*haw 87

http.Handler和http.HandleFunc的模式不是正则表达式或整数.没有办法指定通配符.他们在这里记录.

也就是说,创建自己的处理程序并不难,可以使用正则表达式或任何其他类型的模式.这是一个使用正则表达式(已编译但未经过测试):

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)
}
Run Code Online (Sandbox Code Playgroud)

  • 如果你只是在寻找一个"其他"```式的全能,那么[文档](http://golang.org/pkg/net/http/#ServeMux)需要注意的是` pattern"/"匹配所有与其他注册模式不匹配的路径 (6认同)
  • Gorillatoolkit在处理路径方面可以很好地实现PAT和MUX.唯一的问题是它很慢,我还没有审查代码.至少在他们的API中,可以命名params ......这就是那种功能的全部要点.上面的代码没有提供任何复杂的代码,如果没有命名元素可能没用. (3认同)
  • 由于我想在Go中使用ruby on rails样式路由,我已经启动了允许这种路由映射方式的goweb项目(请参阅http://goweb.googlecode.com/):goweb.MapFunc("/ people/{person_id}" ,处理程序) (2认同)
  • 如何将代码集成到“net/http”的原始示例中。你能给出一个完整的例子吗?谢谢。 (2认同)

Von*_*onC 55

自2011年起,您现在可以(2014年以上)找到其他解决方案.
例如,Gorilla Web工具包mux包提供了所有类型的路由选项:

  • 请求路径上的模式匹配,带有可选的正则表达式.
  • 匹配URL主机和方案,请求方法,标头和查询值.
  • 基于自定义函数匹配.
  • 使用子路由器可以轻松嵌套路由.

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

以下是文章" Gorilla vs Pat vs Routes:Mux Showdown "中的一个例子:

package main

import (
  "github.com/gorilla/mux"
  "log"
  "net/http"
)

func main() {
  rtr := mux.NewRouter()
  rtr.HandleFunc("/user/{name:[a-z]+}/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))
}
Run Code Online (Sandbox Code Playgroud)

有时最好不要只使用另一个"神奇"的包装,但要了解引擎盖下发生了什么

在这种情况下,"魔术"在" gorilla/mux/regexp.go"中定义,并在此处进行测试.
我们的想法是提取命名变量,组装要匹配的正则表达式,创建"反向"模板以构建URL并编译正则表达式以验证URL构建中使用的变量值.

  • 因为有时最好不要只使用另一个"神奇"包,但要了解幕后发生的事情:) (5认同)

Dav*_*man 6

我只是想添加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))
}
Run Code Online (Sandbox Code Playgroud)

它似乎比gorilla/mux(根据GitHub)稍微更受欢迎,并且它还声称需要更少的内存.

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


cai*_*ike 5

这是如何使用来自@evanshaw 的代码示例的示例

func handleDigits(res http.ResponseWriter, req *http.Request) {
    res.Write([]byte("Digits in the URL\n"))
}

func handleStrings(res http.ResponseWriter, req *http.Request) {
    res.Write([]byte("Strings in the URL\n"))
}

func main() {
    handler := &RegexpHandler{}

    reg1, _ := regexp.Compile("/foo-\\d+")
    handler.HandleFunc(reg1, handleDigits)

    reg2, _ := regexp.Compile("/foo-\\w+")
    handler.HandleFunc(reg2, handleStrings)

    http.ListenAndServe(":3000", handler)
}
Run Code Online (Sandbox Code Playgroud)

  • @CSQGB如果你正确地阅读了答案,它会说“这是一个如何使用@evanshaw的代码示例的示例”,它不仅仅是代码。这使用了上面的一个例子。它甚至使用一个名为“RegexpHandler”的不同处理程序,而不是“http.HandleFunc”。 (2认同)