Gorilla mux可选查询值

huangapple go评论82阅读模式
英文:

Gorilla mux optional query values

问题

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

我希望能够在路由中关联查询参数,但这些参数应该是可选的。
这意味着我希望能够在同一个处理程序中捕获/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。

英文:

I've been working on a Go project where gorilla/mux is used as the router.

I need to be able to have query values associated with a route, but these values should be optional.
That means that I'd like to catch both /articles/123 and /articles/123?key=456 in the same handler.

To accomplish so I tried using the r.Queries method that accepts key/value pairs:
router.

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

but this makes only the value (456) optional, but not the key.
So both /articles/123?key=456 and /articles/123?key= are valid, but not /articles/123.

Edit: another requirement is that, after registering the route, I'd like to build them programatically, and I can't seem to work out how to use r.Queries even though the docs specifically state that it's possible (https://github.com/gorilla/mux#registered-urls).

@jmaloney answer works, but doesn't allow to build URLs from names.

答案1

得分: 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
    }

    // 输出:
    // /articles/10?key=[key]
    w.Write([]byte(u.String()))
}
英文:

I would just register your handler twice.

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

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

Here is a working program to demonstrate. Notice that I am using r.FormValue to get the query parameter.

Note: make sure you have an up to date version go get -u github.com/gorilla/mux since a bug of query params not getting added the built URLs was fixed recently.

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

答案2

得分: 18

如果你注册了查询参数,它们是必需的文档

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

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

英文:

If you register query parameters they are required doc:

> All variables defined in the route are required, and their values must conform to the corresponding patterns.

Because those parameters are optional you just need to check for them inside of a handler function: id, found := mux.Vars(r)["id"]. Where found will show if the parameter in the query or not.

答案3

得分: 11

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

urlParams := request.URL.Query()

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

英文:

Seems like the best way to handle optional URL parameters is to define your router as normal without them, then parse the optional params out like this:

urlParams := request.URL.Query()

This returns a map that contains the URL parameters as Key/Value pairs.

huangapple
  • 本文由 发表于 2017年7月29日 00:42:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/45378566.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定