使用MUX包将查询参数传递给Go HTTP请求处理程序

7

我正在尝试将一个额外的参数传递到我发送给Go服务器的请求中 -

websocket.create_connection("ws://<ip>:port/x/y?token="qwerty")

Go服务器实现如下 -
func main() {
    err := config.Parse()
    if err != nil {
        glog.Error(err)
        os.Exit(1)
        return
    }

    flag.Parse()
    defer glog.Flush()

    router := mux.NewRouter()
    http.Handle("/", httpInterceptor(router))

    router.Handle("/v1/x", common.ErrorHandler(stats.GetS)).Methods("GET")
    router.Handle("/v1/x/y", common.ErrorHandler(stats.GetS)).Methods("GET")

    var listen = fmt.Sprintf("%s:%d", config.Config.Ip, config.Config.Port)
    err = http.ListenAndServe(listen, nil)

    if err != nil {
        glog.Error(err)
        os.Exit(1)
    }
}

func httpInterceptor(router http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
        startTime := time.Now()

        if !auth.Auth(w, req) {
            http.Error(w, "Failed authentication", 401)
            return
        }

        router.ServeHTTP(w, req)

        finishTime := time.Now()
        elapsedTime := finishTime.Sub(startTime)

        switch req.Method {
        case "GET":
        case "POST":
        }

    })
}

如何在Go服务器中查找和解析令牌,以便身份验证成功?

库函数

func ParseFromRequest(req *http.Request, keyFunc Keyfunc) (token *Token, err error) {

    // Look for an Authorization header
    if ah := req.Header.Get("Authorization"); ah != "" {
        // Should be a bearer token
        if len(ah) > 6 && strings.ToUpper(ah[0:6]) == "BEARER" {
            return Parse(ah[7:], keyFunc)
        }
    }

    // Look for "access_token" parameter
    req.ParseMultipartForm(10e6)
    if tokStr := req.Form.Get("access_token"); tokStr != "" {
        return Parse(tokStr, keyFunc)
    }

    return nil, ErrNoTokenInRequest

}
3个回答

16

调用 FormValue 方法获取查询参数:

token := req.FormValue("token")

req 是一个 *http.Request

另一种方法是调用ParseForm并直接访问req.Form

if err := req.ParseForm(); err != nil {
   // handle error
}
token := req.Form.Get("token")

在评论中,楼主问如何将"token"映射到外部包正在查找的"access_token"。在调用外部包之前,请执行以下代码:

if err := req.ParseForm(); err != nil {
   // handle error
}
req.Form["access_token"] = req.Form["token"]

当外部包调用req.Form.Get("access_token")时,它将获得与"token"参数相同的值。


酷,谢谢。我如何将此令牌参数传递给上面代码中使用的Auth函数?另一个问题是我正在使用的外部库正在寻找“access_token”参数,而在我的服务器代码中,我将添加此逻辑以处理“token”参数。如何将“token”内部映射到“Access_token”,以便库可以成功验证传递请求中的此令牌? - psbits
图书馆如何获取查询参数?它使用req.Form吗? - Charlie Tumahai
该库有一个ParseFromRequest函数的实现,看起来像这样 -func ParseFromRequest(req *http.Request, keyFunc Keyfunc) (token *Token, err error) {// 查找Authorization头 if ah := req.Header.Get("Authorization"); ah != "" { // 应该是一个Bearer令牌 if len(ah) > 6 && strings.ToUpper(ah[0:6]) == "BEARER" { return Parse(ah[7:], keyFunc) } }// 查找 "access_token" 参数 req.ParseMultipartForm(10e6) if tokStr := req.Form.Get("access_token"); tokStr != "" { return Parse(tokStr, keyFunc) }return nil, ErrNoTokenInRequest} - psbits
有没有办法我可以使用 req.URL.Query().Get("token") 获取令牌并将其分配给 req.Form("access_token")? - psbits
您可以使用 req.ParseForm(); req.Form.Set("access_token", req.URL.Query().Get("token")),在这种情况下,ParseForm 将 req.Form 设置为 req.URL.Query()。第二次调用 req.URL.Query() 没有意义。 - Charlie Tumahai
显示剩余4条评论

5

根据您想解析令牌的方式,如果它来自表单或URL,则需要不同的处理方式。

如果令牌来自表单,则可以使用第一个答案。而如果是来自URL,则建议使用此方法。这对我有效。

token := req.URL.Query().Get("token")

2
Query 方法每次被调用时都会解析查询字符串。首选方法是通过调用 ParseForm 一次性解析查询字符串,并在请求的 Form 字段中访问已解析的参数。FormValue 是一个有用的辅助方法,它将这两个步骤结合起来。 - Charlie Tumahai

0

对于 URL 查询参数:

mux.Vars(r)["token"]

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