美文网首页
go1.13以上版本中对于cookie头部有分号无法解析的问题

go1.13以上版本中对于cookie头部有分号无法解析的问题

作者: 尤旭 | 来源:发表于2022-03-22 18:50 被阅读0次

    现象描述

    cookie字段中以分号开头,在go获取cookie的时候,就获取不到这个字段,举例待获取的cookie字段是token=abc,但是cookie中写入的是;token=abc,此时在go1.13版本以上就无法正确获得到token这个值。

    分析代码

    /usr/local/go/src/net/http/cookie.go 这个文件中的 readCookies方法,最关键的就是if splitIndex := strings.Index(line, ";"); splitIndex > 0 {这行
    1.13版本

    // readCookies parses all "Cookie" values from the header h and
    // returns the successfully parsed Cookies.
    //
    // if filter isn't empty, only cookies of that name are returned
    func readCookies(h Header, filter string) []*Cookie {
        lines := h["Cookie"]
        if len(lines) == 0 {
            return []*Cookie{}
        }
    
        cookies := make([]*Cookie, 0, len(lines)+strings.Count(lines[0], ";"))
        for _, line := range lines {
            line = textproto.TrimString(line)
    
            var part string
            for len(line) > 0 { // continue since we have rest
                if splitIndex := strings.Index(line, ";"); splitIndex > 0 {// 这行是关键
                    part, line = line[:splitIndex], line[splitIndex+1:]
                } else {
                    part, line = line, ""
                }
                part = textproto.TrimString(part)
                if len(part) == 0 {
                    continue
                }
                name, val := part, ""
                if j := strings.Index(part, "="); j >= 0 {
                    name, val = name[:j], name[j+1:]
                }
                if !isCookieNameValid(name) {
                    continue
                }
                if filter != "" && filter != name {
                    continue
                }
                val, ok := parseCookieValue(val, true)
                if !ok {
                    continue
                }
                cookies = append(cookies, &Cookie{Name: name, Value: val})
            }
        }
        return cookies
    }
    

    1.12版本

    // readCookies parses all "Cookie" values from the header h and
    // returns the successfully parsed Cookies.
    //
    // if filter isn't empty, only cookies of that name are returned
    func readCookies(h Header, filter string) []*Cookie {
        lines, ok := h["Cookie"]
        if !ok {
            return []*Cookie{}
        }
    
        cookies := []*Cookie{}
        for _, line := range lines {
            parts := strings.Split(strings.TrimSpace(line), ";") // 这行是关键
            if len(parts) == 1 && parts[0] == "" {
                continue
            }
            // Per-line attributes
            for i := 0; i < len(parts); i++ {
                parts[i] = strings.TrimSpace(parts[i])
                if len(parts[i]) == 0 {
                    continue
                }
                name, val := parts[i], ""
                if j := strings.Index(name, "="); j >= 0 {
                    name, val = name[:j], name[j+1:]
                }
                if !isCookieNameValid(name) {
                    continue
                }
                if filter != "" && filter != name {
                    continue
                }
                val, ok := parseCookieValue(val, true)
                if !ok {
                    continue
                }
                cookies = append(cookies, &Cookie{Name: name, Value: val})
            }
        }
        return cookies
    }
    

    原因分析

    在1.12版本的时候,是通过分号来分割来获取字段的,而1.13版本中是判断分号所在位置,而恰巧;token是分号的位置是0就会走到他的else分支,造成无法正确获得字段。
    虽然这是一个写cookie不够标准造成的问题,但是如果写cookie方无法修改的时候,我们只能自己想办法。

    解决办法

    那么如果后端来解决这个问题,我的方式是,通过中间件加工request.header,重写cookie,以gin框架为例
    代码如下

    func(c *gin.Context) {
            if len(c.Request.Header["Cookie"]) > 0 {
                for _, ccv := range c.Request.Header["Cookie"] {
                    ccv = textproto.TrimString(ccv)
                    if fIndex := strings.Index(ccv, ";"); fIndex == 0 {
                        c.Request.Header["Cookie"] = append(c.Request.Header["Cookie"], ccv[fIndex+1:])
                    }
                }
            }
    }
    

    这样cookie中就有一份token=abc的数据了,在后续的循环中可以正常获得。

    相关文章

      网友评论

          本文标题:go1.13以上版本中对于cookie头部有分号无法解析的问题

          本文链接:https://www.haomeiwen.com/subject/yxrfuqtx.html