Golang Gin 获取 cookie 的 JSON。

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

golang gin get cookie json

问题

我使用的是gin@v1.9.0版本。

尝试从请求中获取cookie。

cookie示例:

key={"ckey": "cvalue"}

代码:

token, err := c.Request.Cookie("key")

返回错误:

http: named cookie not present

但是如果没有花括号,就可以正常工作。

cookie示例:

key=cvalue

接收到的结果是:

token = "key=cvalue"

英文:

I use gin@v1.9.0

Trying to get cookie from request

Cookie example:

key={"ckey": "cvalue"}

code:

token, err := c.Request.Cookie("key")

Returns error

http: named cookie not present

But without curly braces, works fine

Cookie example:

key=cvalue

receive
token = "key=cvalue"

答案1

得分: 1

问题出现是因为 cookie 值的格式问题。

让我们看一下来自 net/http 的这些代码:

// Strip the quotes, if present.
if allowDoubleQuote && len(raw) > 1 && raw[0] == '"' && raw[len(raw)-1] == '"' {
    raw = raw[1 : len(raw)-1]
}

这个语句用于从字符串的开头和结尾去除 "。但是无法移除 {"ckey": "cvalue"} 中的引号。

然后它调用另一个函数,这个函数是一个循环,遍历每个字符并检查字符是否是有效的字节。

for i := 0; i < len(raw); i++ {
    if !validCookieValueByte(raw[i]) {
        return "", false
    }
}

validCookieValueByte 的实现如下:

func validCookieValueByte(b byte) bool {
    return 0x20 <= b && b < 0x7f && b != '"' && b != ';' && b != '\\'
}

在这里检查失败,因为 {&quot;ckey&quot;: &quot;cvalue&quot;} 中有一个 "

让我们用一个示例代码来检查:

func main() {
    router := gin.Default()

    router.GET("/get-cookie", func(c *gin.Context) {
        cookie, err := c.Request.Cookie("key")
        if err != nil {
            c.String(http.StatusBadRequest, err.Error())
            return
        }
        c.String(http.StatusOK, fmt.Sprintf("token = key=%v", cookie.Value))
    })

    router.Run(":8080")
}

这个会失败:

curl --request GET \
  --url http://localhost:8080/get-cookie \
  --cookie key='{&quot;ckey&quot;: &quot;cvalue&quot;}'

但这个会成功:

curl --request GET \
  --url http://localhost:8080/get-cookie \
  --cookie key='{ckey: cvalue}'

我们可以使用 http.Cookie 将 cookie 设置为 JSON 格式:

val := `{&quot;ckey&quot;: &quot;cvalue&quot;}`
cookie := &http.Cookie{
    Name:  "key",
    Value: val,
}
http.SetCookie(c.Writer, cookie)

在保存值之前,SetCookie 会移除 "

英文:

The issue is happening because of the cookie value format.

Let's look at these codes from net/http

 // Strip the quotes, if present.
if allowDoubleQuote &amp;&amp; len(raw) &gt; 1 &amp;&amp; raw[0] == &#39;&quot;&#39; &amp;&amp; raw[len(raw)-1] == &#39;&quot;&#39; {
	raw = raw[1 : len(raw)-1]
}

this statement is used to strip the &quot; from the beginning and the end of the string.
{&quot;ckey&quot;: &quot;cvalue&quot;} the quotes from this string cannot be removed.

And then it call another function which is a loop that iterates through each characters and checks the character is a valid byte.

   for i := 0; i &lt; len(raw); i++ {
		if !validCookieValueByte(raw[i]) {
			return &quot;&quot;, false
		}
	}

validCookieValueByte implementation

func validCookieValueByte(b byte) bool {
	return 0x20 &lt;= b &amp;&amp; b &lt; 0x7f &amp;&amp; b != &#39;&quot;&#39; &amp;&amp; b != &#39;;&#39; &amp;&amp; b != &#39;\\&#39;
}

and the check is failing at here. Because we have a &quot; in {&quot;ckey&quot;: &quot;cvalue&quot;}

Let's check with a sample code

func main() {
	router := gin.Default()

	router.GET(&quot;/get-cookie&quot;, func(c *gin.Context) {
		cookie, err := c.Request.Cookie(&quot;key&quot;)
		if err != nil {
			c.String(http.StatusBadRequest, err.Error())
			return
		}
		c.String(http.StatusOK, fmt.Sprintf(&quot;token = key=%v&quot;, cookie.Value))
	})

	router.Run(&quot;:8080&quot;)
}

This will fail

curl --request GET \
  --url http://localhost:8080/get-cookie \
  --cookie key=&#39;{&quot;ckey&quot;: &quot;cvalue&quot;}&#39;

but this will succeed

curl --request GET \
  --url http://localhost:8080/get-cookie \
  --cookie key=&#39;{ckey: cvalue}&#39;

We can use http.Cookie to set the cookie as json

val := `{&quot;ckey&quot;: &quot;cvalue&quot;}`
cookie := &amp;http.Cookie{
	Name:  &quot;key&quot;,
	Value: val,
}
http.SetCookie(c.Writer, cookie)

SetCookie will remove the &quot; before saving the value.

huangapple
  • 本文由 发表于 2023年5月18日 18:55:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76280101.html
匿名

发表评论

匿名网友

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

确定