【问题标题】:Gorilla mux optional query valuesGorilla mux 可选查询值
【发布时间】:2018-01-04 19:44:54
【问题描述】:

我一直在做一个使用 gorilla/mux 作为路由器的 Go 项目。

我需要能够将查询值与路由关联,但这些值应该是可选的。 这意味着我想在同一个处理程序中同时捕获 /articles/123/articles/123?key=456

为了完成,我尝试使用接受键/值对的r.Queries 方法: 路由器。

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

但这使得只有值 (456) 是可选的,而不是 key。 所以/articles/123?key=456/articles/123?key= 都有效,但/articles/123 无效。

编辑:另一个要求是,在注册路线之后,我想以编程方式构建它们,我似乎无法弄清楚如何使用r.Queries,即使文档明确指出这是可能的(@ 987654321@).

@jmaloney 回答有效,但不允许从名称构建 URL。

【问题讨论】:

  • @smarx 我已经看到了这个问题,但它对我不起作用有两个原因:1. 它阻止我在处理程序 2 中使用 mux.Vars(req)["tab"]。它没有允许我按名称构建注册 URL(我已经更新了问题)

标签: go gorilla mux


【解决方案1】:

似乎处理 可选 URL 参数的最佳方法是在没有它们的情况下将您的路由器定义为正常,然后像这样解析可选参数:

urlParams := request.URL.Query()

这会返回一个映射,其中包含作为键/值对的 URL 参数。

【讨论】:

    【解决方案2】:

    我只会注册你的处理程序两次。

    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()))
    }
    

    【讨论】:

    • 我尝试过这样做,并且成功了,尽管我不知道这是否是黑客行为。唯一的问题是我想使用注册的 URL 按名称反向构建 URL 并使用它们处理查询值,但它似乎不起作用。我会更新问题。
    • @stassinari 我认为我最近的编辑应该可以解决您的问题。
    • 谢谢@jmaloney,我能够让它工作。但是有一个问题:您使用r.FormValue 而不是mux.Vars 有什么原因吗?我似乎能够让它工作
    • 另外,为了能够使用和不使用参数来构建 URL,我对路由使用了两个不同的名称,就像你的方法一样,一个名称丢失了,并且用两个“重载”了路由相同的名称与多路复用器混淆,似乎不起作用。
    • @stassinari 我使用r.FormValue,因为如果找不到密钥,它将返回一个空字符串,如果请求转到第二个处理程序,则使用mux.Vars 将找不到mux.Vars,处理这种情况还使您必须检查地图是否具有该值。我只使用查询参数“命名”了路由,因为使用空白查询构建 url 仍然有效并且导致代码和逻辑更少。例如,在上面的代码中,如果用户点击第二条路线,输出将只是/articles/10?key=,这很好。
    【解决方案3】:

    如果您注册查询参数,则它们是必需的doc

    路由中定义的所有变量都是必需的,其值必须符合相应的模式。

    因为这些参数是可选的,您只需要在处理函数中检查它们:id, found := mux.Vars(r)["id"]。其中found 将显示查询中的参数是否存在。

    【讨论】:

    • 这才是真正的答案。
    猜你喜欢
    • 2018-02-13
    • 2017-09-08
    • 2020-11-10
    • 2014-12-22
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 2015-05-11
    • 2015-04-07
    相关资源
    最近更新 更多