HTTP是一个无状态的协议。
这意味着服务器不会记录客户的状态。但是有时候服务器需要知道客户端的状态,这个时候就可以使用Cookie了。
1. Cookie in Golang
在Go中,定义了Cookie的结构:
type Cookie struct {
Name string
Value string
Path string // optional
Domain string // optional
Expires time.Time // optional
RawExpires string // for reading cookies only
// MaxAge=0 means no 'Max-Age' attribute specified.
// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
// MaxAge>0 means Max-Age attribute present and given in seconds
MaxAge int
Secure bool
HttpOnly bool
SameSite SameSite
Raw string
Unparsed []string // Raw text of unparsed attribute-value pairs
}
其实Cookie就是一个key-value对,用来存储一些简单的信息。也就是上面的字段中,Name
和Value
是必须的,其余的都是可选的。
Expires
和MaxAge
都可以用来设置Cookie的有效期。不同在于:
Expires
指定了Cookie过期的具体时间,比如一个Cookie会在2020-02-02 02:02:02过期;MaxAge
指定了一个Cookie在被浏览器创建后可以存在的时间,单位是秒;- 几乎所有的浏览器都支持
Expires
,但是IE6、IE7和IE8不支持MaxAge
。
使用这两种方式不是Go的原因,而是浏览器的支持情况决定的。
2. 设置Cookie
服务器设置Cookie本质上就是将一个字符串写入response中的”Set-Cookie” Header中。而这个写入的字符串,是对Cookie结构的一个序列化结果(就是Cookie.String()
方法)。
c := http.Cookie{
Name: "cookie",
Value: "go web",
}
w.Header().Set("Set-Cookie", c.String())
打开浏览器可以看到下面的结果:
也可以使用http.SetCookie()
方法:
c := http.Cookie{
Name: "cookie",
Value: "go web",
}
http.SetCookie(w, &c)
结果也是一样,不过要注意,这里使用的是Cookie的指针。
3. 读取Cookie
服务器写入Cookie的Header是Set-Cookie
,浏览器向服务器传递Cookie的Header是Cookie
,可以通过这个Header来读取浏览器的Cookie:
h := r.Header["Cookie"]
这样获取到的是所有的Cookie切片。为了获取所有的Cookie,还可以使用下面的方法:
// Cookies parses and returns the HTTP cookies sent with the request.
func (r *Request) Cookies() []*Cookie {
return readCookies(r.Header, "")
}
上面两个方法获得的是所有的Cookie,还可以获取指定的Cookie:
// Cookie returns the named cookie provided in the request or
// ErrNoCookie if not found.
// If multiple cookies match the given name, only one cookie will
// be returned.
func (r *Request) Cookie(name string) (*Cookie, error) {
for _, c := range readCookies(r.Header, name) {
return c, nil
}
return nil, ErrNoCookie
}
不过这会在Cookie不存在的时候返回一个错误。具体使用如下:
c, err := r.Cookie("cookie")
if err != nil {
fmt.Println("no such cookie")
}
4. 删除一个Cookie
Go里没有删除Cookie的方法,不过可以通过设置一个Cookie有效期来间接删除一个Cookie。
可以将一个Cookie的Expires
设置为一个过去的时间,或者MaxAge
设置为负数,就可以删除一个Cookie了:
c := http.Cookie{
Name: "old_cookie",
MaxAge: -1,
Expires: time.Unix(1, 0),
}
http.SetCookie(w, &c)
这篇文章简单介绍了一下在Go中如果使用Cookie,包括添加、读取以及删除。
To Be Continued…