大猩猩mux可选查询值

33
我一直在开发一个Go项目,其中使用gorilla/mux作为路由器。
我需要能够将查询值与路由相关联,但这些值应该是可选的。这意味着我想在同一个处理程序中捕获/articles/123/articles/123?key=456
为了实现这一点,我尝试使用接受键/值对的r.Queries方法:router。
  Path("/articles/{id:[0-9]+}").Queries("key", "{[0-9]*?}")

但这仅使值 (456) 可选,而不是 key。 因此,/articles/123?key=456/articles/123?key= 都是有效的,但是 /articles/123 不是。

编辑:另一个要求是,在注册路由后,我想以编程方式构建它们,但我似乎无法弄清如何使用 r.Queries,即使文档明确说明它是可能的 (https://github.com/gorilla/mux#registered-urls)。

@jmaloney 的答案可行,但不允许根据名称构建 URL。


1
一种方法:https://dev59.com/7FcQ5IYBdhLWcg3wEPoK - user94559
@smarx 我看过那个问题,但有两个原因它对我不起作用:
  1. 它阻止我在我的处理程序中使用 mux.Vars(req)["tab"]
  2. 它不允许我按名称构建注册的URL(我已更新问题)
- stassinari
3个回答

34

我只会让您注册两次处理程序。

router.Path("/articles/{id:[0-9]+}").
    Queries("key", "{[0-9]*?}").
    HandlerFunc(YourHandler).
    Name("YourHandler")

router.Path("/articles/{id:[0-9]+}").HandlerFunc(YourHandler)

这里是一个可工作的程序示例。请注意,我正在使用r.FormValue来获取查询参数。

注意:确保你拥有最新版本go get -u github.com/gorilla/mux,因为最近修复了一个在构建URL时未添加查询参数的错误。

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/mux"
)

var router = mux.NewRouter()

func main() {
    router.Path("/articles/{id:[0-9]+}").Queries("key", "{key}").HandlerFunc(YourHandler).Name("YourHandler")
    router.Path("/articles/{id:[0-9]+}").HandlerFunc(YourHandler)

    if err := http.ListenAndServe(":9000", router); err != nil {
        log.Fatal(err)
    }
}

func YourHandler(w http.ResponseWriter, r *http.Request) {
    id := mux.Vars(r)["id"]
    key := r.FormValue("key")

    u, err := router.Get("YourHandler").URL("id", id, "key", key)
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }

    // Output:
    // /articles/10?key=[key]
    w.Write([]byte(u.String()))
}

谢谢@jmaloney,我已经成功让它工作了。不过有一个问题:你使用r.FormValue而不是mux.Vars的原因是什么?我似乎也能让它工作。 - stassinari
2
@stassinari 我使用 r.FormValue,因为如果找不到键,则会返回一个空字符串,如果请求进入第二个处理程序,则使用 mux.Vars 将无法找到 key,处理该情况还需要检查映射是否具有该值。我仅对带有查询参数的路由进行了“命名”,因为使用空白查询构建 URL 仍然是有效的,并且可以减少代码和逻辑。例如,在上面的代码中,如果用户访问第二个路由,则输出将只是 /articles/10?key=,这是完全可以接受的。 - jmaloney
那么如果我有10个可选参数,我必须为每种可能的组合声明一个路由吗?看起来很繁琐... - sgt-hartman
@sgt-hartman,您可以在第一个处理程序中定义所有10个参数。就我个人而言,如果我期望有一堆可选的查询参数,我不会使用mux的此功能。我将定义没有任何参数的处理程序,并使用url包构造URL查询(如果需要)。当您希望为同一路由设置多个处理程序但通过查询参数将它们分开时,“Queries”功能似乎最有用。 - jmaloney
@jmaloney 是的,查询字符串通常用作可选参数。必需的参数应该放在URI中。如果库能够处理这个问题,那将是一个很好的补充。 - sgt-hartman
显示剩余5条评论

18
如果您注册了查询参数,则这些参数是必需的文档
路由定义中所有变量都是必需的,它们的值必须符合相应的模式。
因为这些参数是可选的,所以您只需要在处理程序函数中检查它们:id, found := mux.Vars(r)["id"]。其中found将显示查询参数是否存在。

1
这是真正的答案。 - Corey Ogburn

11

似乎处理可选的URL参数的最佳方法是正常定义路由而不使用它们,然后像这样解析出可选参数:

urlParams := request.URL.Query()

这将返回一个包含URL参数键/值对的映射。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接