【问题标题】:golang mux, routing wildcard & custom func matchgolang mux、路由通配符和自定义函数匹配
【发布时间】:2014-03-07 00:48:22
【问题描述】:

我正在使用mux 包,它似乎工作得很好,只是它似乎不支持复杂的路线,或者至少我不明白它是如何工作的。 我有以下几条路线:

router := mux.NewRouter()
router.HandleFunc("/{productid}/{code}", product)
router.HandleFunc("/{user}", userHome)
router.HandleFunc("/search/price", searchPage)

所以我有两个问题:

  • 如何定义通配符路由,例如 /search/price/*,以便 /search/price/29923/rage/200/color=red 等请求可以匹配?

  • 是否可以将自定义条件添加到现有路线?例如如果路由是/{productid}/{code}并且函数x返回true,使用这个handlerTrue,如果它返回false使用handlerFalse

我尝试在路由中添加类似.MatcherFunc(myfunction(ip)bool) 的内容,但它抱怨路由器没有这样的方法。

目前我正在处理程序中处理“自定义”条件。

【问题讨论】:

  • 标题应该会提到它是gorilla mux,因为go stdlib中有mux,所以标题有点混乱。

标签: go mux


【解决方案1】:

您可以使用正则表达式。类似的东西

router.HandleFunc(`/search/price/{rest:[a-zA-Z0-9=\-\/]+}`, searchPage)

这样,rest 将捕获所有内容,因此在您的示例中,rest 将是 29923/rage/200/color=red。你需要在你的代码中解析它。

不过,您可能想要一些类似的可选参数。

router.HandleFunc(`/search{price:(\/price\/[0-9]+)?}{rage:(\/rage\/[0-9]+)?}{color:(\/color=[a-z]+)?}`, searchPage)

之后,你会得到 vars price = "/price/29923"rage = "/rage/200"color = "/color=red",你仍然需要解析它们,但它更容易,你可以控制哪些参数是有效的。如果您跳过某些参数,它会按预期工作,例如。 /search/price/29923/color=red 只会给出一个空的 rage 变量,但仍然匹配。

我不太明白你的第二个问题。

【讨论】:

  • 对不起。对于涉及子表达式的第二种解决方案,我认为您需要这个多路复用器的分支:github.com/gorilla/mux/pull/11,这是我在上一个项目中使用的。
  • 正则表达式抛出错误:“未知转义序列”
  • 是的,"" 应该是 ``。已编辑。
  • 它不会抛出错误,但也不会处理路由(我得到 404 )例如/search/price/0.000/asdasd/asdasd
  • 点不匹配,您的初始示例没有点。将其添加到模式中:[a-zA-Z0-9=\-\/\.]+
【解决方案2】:

我不太确定您是否需要一条“通配符”路由:您只需要一条带有多个参数的路由:

/search/price/{price}/rage/{id}/color 可以工作,注意查询字符串不需要包含在匹配器中(您可以通过request.URL.Query 访问这些字符串,而您可以通过mux.Vars 访问多路复用变量。您还可以使用正则表达式来缩小范围降低接受的参数。

它还有助于区分您的用户和产品路线,也许可以通过在它们前面加上 /user/{id}/products/{id}/{code}(尤其是语义)。

MatcherFunc 而言,您需要确保您的函数使用与 MatcherFunc 相同的签名(这是一种类型):func MatchIPAddresses(*http.Request, *RouteMatch) bool 会解决它。您可以通过 Request 结构访问 IP 地址,如果您希望在代理后面,请检查 r.RemoteAddrr.Header.Get("X-Forwarded-For")。如果一个为空(""),我通常会检查两者。

即(粗略;你可以把它清理一下!)

func MatchIPAddresses(r *http.Request, rm *RouteMatch) bool {
    if r.RemoteAddr == 8.8.8.8 {
        return true
    } else if r.Header.Get("X-Forwarded-For") == 8.8.8.8 {
        return true
    }

    return false
}

【讨论】:

  • 未定义:RouteMatch,不能在函数参数中使用 myfunction(, *RouteMatch) (type bool) 作为 mux.MatcherFunc 类型
  • 我已经修正了我的例子。我还强烈建议阅读 Gorilla Mux 文档,其中有一个类似的示例,说明如何在页面的中间编写 MatcherFunc:gorillatoolkit.org/pkg/mux
  • 我之前已经阅读过文档来发布问题。我认为您的答案基本上是从文档中复制的,除了 ip 函数。
【解决方案3】:

要将自定义 MatcherFunc 与 gorilla mux 一起使用,您需要确保您的匹配器实际上是 mux.MatcherFunc 类型。这是因为 MatcheFunc 不是接口类型

// From mux/route.go line 303
// MatcherFunc is the function signature used by custom matchers.
type MatcherFunc func(*http.Request, *RouteMatch) bool

所以你必须这样做:

var myMatcher mux.MatcherFunc = func(request *http.Request, match *mux.RouteMatch) bool {
  // Your custom logic
  return trueOrFalse
}

// You can then use it on your route like this.
router := mux.NewRouter()
router.HandleFunc("/{productid}/{code}", product).MatcherFunc(myMatcher)

【讨论】:

    【解决方案4】:

    使用 chi 作为路由器,您可以执行以下操作:

    由于正则表达式从不匹配斜线/,您可以简单地匹配*

    例如为/search/price/29923/rage/200/color=red

    router.Get(`/search/price/*`, priceHandler)
    
    func DashboardFilesHandler(w http.ResponseWriter, r *http.Request) {
        path := myhandler.UrlParam(r, "*")
        // path will be '29923/rage/200/color=red'
    }
    

    另请参阅:https://godoc.org/github.com/go-chi/chi

    名称后跟冒号的占位符允许使用正则 表达式匹配,例如 {number:\d+}。正则表达式 语法是 Go 的普通正则表达式 RE2 语法,除了正则 不支持包含 { 或 } 的表达式,并且 / 永远不会 匹配。 允许匿名正则表达式模式,使用空字符串 在占位符的冒号之前,例如 {:\d+}

    星号的特殊占位符与请求的其余部分匹配 URL。 模式中的任何尾随字符都将被忽略。这是 唯一将匹配 / 字符的占位符。

    【讨论】:

      猜你喜欢
      • 2021-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-29
      • 2014-08-13
      • 2020-08-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多