2017-12-29 16:03:30 +08:00
|
|
|
|
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
|
|
|
|
//
|
|
|
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
|
|
|
// If a copy of the MIT was not distributed with this file,
|
|
|
|
|
// You can obtain one at https://gitee.com/johng/gf.
|
2017-12-30 23:49:55 +08:00
|
|
|
|
//
|
|
|
|
|
// HTTP Cookie管理对象,
|
|
|
|
|
// 由于Cookie是和HTTP请求挂钩的,因此被包含到 ghttp 包中进行管理
|
2017-12-12 17:25:50 +08:00
|
|
|
|
package ghttp
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"sync"
|
2017-12-30 23:49:55 +08:00
|
|
|
|
"time"
|
2017-12-13 11:36:29 +08:00
|
|
|
|
"strings"
|
2017-12-13 14:13:36 +08:00
|
|
|
|
"net/http"
|
|
|
|
|
"gitee.com/johng/gf/g/os/gtime"
|
2017-12-30 23:49:55 +08:00
|
|
|
|
"gitee.com/johng/gf/g/container/gmap"
|
2017-12-13 11:36:29 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
2017-12-30 23:49:55 +08:00
|
|
|
|
gDEFAULT_PATH = "/" // 默认path
|
|
|
|
|
gDEFAULT_MAX_AGE = 86400 // 默认cookie有效期
|
|
|
|
|
SESSION_ID_NAME = "gfsessionid" // 默认存放Cookie中的SessionId名称
|
2017-12-12 17:25:50 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// cookie对象
|
|
|
|
|
type Cookie struct {
|
|
|
|
|
mu sync.RWMutex // 并发安全互斥锁
|
|
|
|
|
data map[string]CookieItem // 数据项
|
2017-12-13 14:13:36 +08:00
|
|
|
|
domain string // 默认的cookie域名
|
2017-12-12 17:25:50 +08:00
|
|
|
|
request *ClientRequest // 所属HTTP请求对象
|
|
|
|
|
response *ServerResponse // 所属HTTP返回对象
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// cookie项
|
|
|
|
|
type CookieItem struct {
|
|
|
|
|
value string
|
2017-12-30 23:49:55 +08:00
|
|
|
|
domain string // 有效域名
|
|
|
|
|
path string // 有效路径
|
|
|
|
|
expire int // 过期时间
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-30 23:49:55 +08:00
|
|
|
|
// 包含所有当前服务器正在服务的Cookie
|
|
|
|
|
var cookies = gmap.NewUintInterfaceMap()
|
|
|
|
|
|
|
|
|
|
// 创建一个cookie对象,与传入的请求对应
|
2017-12-12 17:25:50 +08:00
|
|
|
|
func NewCookie(r *ClientRequest, w *ServerResponse) *Cookie {
|
2017-12-31 12:15:04 +08:00
|
|
|
|
if r := GetCookie(r.Id); r != nil {
|
2017-12-30 23:49:55 +08:00
|
|
|
|
return r
|
|
|
|
|
}
|
|
|
|
|
c := &Cookie {
|
2017-12-12 17:25:50 +08:00
|
|
|
|
data : make(map[string]CookieItem),
|
2017-12-13 14:13:36 +08:00
|
|
|
|
domain : defaultDomain(r),
|
2017-12-12 17:25:50 +08:00
|
|
|
|
request : r,
|
|
|
|
|
response : w,
|
|
|
|
|
}
|
2017-12-13 14:13:36 +08:00
|
|
|
|
c.init()
|
2017-12-31 12:15:04 +08:00
|
|
|
|
cookies.Set(uint(r.Id), c)
|
2017-12-13 14:13:36 +08:00
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-30 23:49:55 +08:00
|
|
|
|
// 获取一个已经存在的Cookie对象
|
|
|
|
|
func GetCookie(requestid uint64) *Cookie {
|
|
|
|
|
if r := cookies.Get(uint(requestid)); r != nil {
|
|
|
|
|
return r.(*Cookie)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-13 14:13:36 +08:00
|
|
|
|
// 获取默认的domain参数
|
|
|
|
|
func defaultDomain(r *ClientRequest) string {
|
|
|
|
|
return strings.Split(r.Host, ":")[0]
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从请求流中初始化
|
|
|
|
|
func (c *Cookie) init() {
|
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
for _, v := range c.request.Cookies() {
|
|
|
|
|
c.data[v.Name] = CookieItem {
|
2017-12-13 14:13:36 +08:00
|
|
|
|
v.Value, v.Domain, v.Path, v.Expires.Second(),
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-30 23:49:55 +08:00
|
|
|
|
// 获取SessionId
|
|
|
|
|
func (c *Cookie) SessionId() string {
|
2017-12-31 12:15:04 +08:00
|
|
|
|
v := c.Get(SESSION_ID_NAME)
|
|
|
|
|
if v == "" {
|
|
|
|
|
v = makeSessionId()
|
|
|
|
|
c.SetSessionId(v)
|
|
|
|
|
}
|
|
|
|
|
return v
|
2017-12-30 23:49:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置SessionId
|
|
|
|
|
func (c *Cookie) SetSessionId(sessionid string) {
|
|
|
|
|
c.Set(SESSION_ID_NAME, sessionid)
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-13 11:36:29 +08:00
|
|
|
|
// 设置cookie,使用默认参数
|
|
|
|
|
func (c *Cookie) Set(key, value string) {
|
2017-12-13 14:13:36 +08:00
|
|
|
|
c.SetCookie(key, value, c.domain, gDEFAULT_PATH, gDEFAULT_MAX_AGE)
|
2017-12-13 11:36:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置cookie,带详细cookie参数
|
|
|
|
|
func (c *Cookie) SetCookie(key, value, domain, path string, maxage int) {
|
2017-12-12 17:25:50 +08:00
|
|
|
|
c.mu.Lock()
|
|
|
|
|
defer c.mu.Unlock()
|
|
|
|
|
c.data[key] = CookieItem {
|
2017-12-13 14:13:36 +08:00
|
|
|
|
value, domain, path, int(gtime.Second()) + maxage,
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-13 14:13:36 +08:00
|
|
|
|
// 查询cookie
|
2017-12-12 17:25:50 +08:00
|
|
|
|
func (c *Cookie) Get(key string) string {
|
|
|
|
|
c.mu.RLock()
|
|
|
|
|
defer c.mu.RUnlock()
|
|
|
|
|
if r, ok := c.data[key]; ok {
|
2017-12-13 14:13:36 +08:00
|
|
|
|
if r.expire >= 0 {
|
|
|
|
|
return r.value
|
|
|
|
|
} else {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-30 23:49:55 +08:00
|
|
|
|
// 标记该cookie在对应的域名和路径失效
|
2017-12-13 14:13:36 +08:00
|
|
|
|
// 删除cookie的重点是需要通知浏览器客户端cookie已过期
|
2017-12-30 23:49:55 +08:00
|
|
|
|
func (c *Cookie) Remove(key, domain, path string) {
|
|
|
|
|
c.SetCookie(key, "", domain, path, -86400)
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-31 12:15:04 +08:00
|
|
|
|
// 请求完毕后删除已经存在的Cookie对象
|
|
|
|
|
func (c *Cookie) Close() {
|
|
|
|
|
cookies.Remove(uint(c.request.Id))
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-12 17:25:50 +08:00
|
|
|
|
// 输出到客户端
|
|
|
|
|
func (c *Cookie) Output() {
|
|
|
|
|
c.mu.RLock()
|
|
|
|
|
defer c.mu.RUnlock()
|
2017-12-30 23:49:55 +08:00
|
|
|
|
// 自动更新SessionId的过期时间
|
|
|
|
|
sitem := c.data[SESSION_ID_NAME]
|
|
|
|
|
minex := int(gtime.Second()) + gDEFAULT_MAX_AGE
|
|
|
|
|
if sitem.expire < minex {
|
|
|
|
|
sitem.expire = minex
|
|
|
|
|
c.data[SESSION_ID_NAME] = sitem
|
|
|
|
|
}
|
2017-12-12 17:25:50 +08:00
|
|
|
|
for k, v := range c.data {
|
2017-12-13 14:13:36 +08:00
|
|
|
|
if v.expire == 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2017-12-30 23:49:55 +08:00
|
|
|
|
http.SetCookie(
|
|
|
|
|
c.response.ResponseWriter,
|
|
|
|
|
&http.Cookie {
|
|
|
|
|
Name : k,
|
|
|
|
|
Value : v.value,
|
|
|
|
|
Domain : v.domain,
|
|
|
|
|
Path : v.path,
|
|
|
|
|
Expires : time.Unix(int64(v.expire), 0),
|
|
|
|
|
},
|
|
|
|
|
)
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
}
|