Golang Gin 获取 cookie 的 JSON。

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

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 的这些代码:

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

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

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

  1. for i := 0; i < len(raw); i++ {
  2. if !validCookieValueByte(raw[i]) {
  3. return "", false
  4. }
  5. }

validCookieValueByte 的实现如下:

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

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

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

  1. func main() {
  2. router := gin.Default()
  3. router.GET("/get-cookie", func(c *gin.Context) {
  4. cookie, err := c.Request.Cookie("key")
  5. if err != nil {
  6. c.String(http.StatusBadRequest, err.Error())
  7. return
  8. }
  9. c.String(http.StatusOK, fmt.Sprintf("token = key=%v", cookie.Value))
  10. })
  11. router.Run(":8080")
  12. }

这个会失败:

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

但这个会成功:

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

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

  1. val := `{&quot;ckey&quot;: &quot;cvalue&quot;}`
  2. cookie := &http.Cookie{
  3. Name: "key",
  4. Value: val,
  5. }
  6. 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

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

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.

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

validCookieValueByte implementation

  1. func validCookieValueByte(b byte) bool {
  2. 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;
  3. }

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

  1. func main() {
  2. router := gin.Default()
  3. router.GET(&quot;/get-cookie&quot;, func(c *gin.Context) {
  4. cookie, err := c.Request.Cookie(&quot;key&quot;)
  5. if err != nil {
  6. c.String(http.StatusBadRequest, err.Error())
  7. return
  8. }
  9. c.String(http.StatusOK, fmt.Sprintf(&quot;token = key=%v&quot;, cookie.Value))
  10. })
  11. router.Run(&quot;:8080&quot;)
  12. }

This will fail

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

but this will succeed

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

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

  1. val := `{&quot;ckey&quot;: &quot;cvalue&quot;}`
  2. cookie := &amp;http.Cookie{
  3. Name: &quot;key&quot;,
  4. Value: val,
  5. }
  6. 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:

确定