gf/g/net/ghttp/http_server_cookie.go

161 lines
4.0 KiB
Go
Raw Normal View History

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.
//
// HTTP Cookie管理对象
// 由于Cookie是和HTTP请求挂钩的因此被包含到 ghttp 包中进行管理
2017-12-31 18:19:58 +08:00
package ghttp
import (
"sync"
"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"
"gitee.com/johng/gf/g/container/gmap"
2017-12-13 11:36:29 +08:00
)
const (
gDEFAULT_PATH = "/" // 默认path
gDEFAULT_MAX_AGE = 86400*365 // 默认cookie有效期(一年)
SESSION_ID_NAME = "gfsessionid" // 默认存放Cookie中的SessionId名称
)
// cookie对象
type Cookie struct {
mu sync.RWMutex // 并发安全互斥锁
data map[string]CookieItem // 数据项
2017-12-13 14:13:36 +08:00
domain string // 默认的cookie域名
2018-01-02 16:35:13 +08:00
request *Request // 所属HTTP请求对象
response *Response // 所属HTTP返回对象
}
// cookie项
type CookieItem struct {
value string
domain string // 有效域名
path string // 有效路径
expire int // 过期时间
}
2018-01-08 11:38:31 +08:00
// 包含所有当前服务器正在服务的Cookie(每个请求一个Cookie对象)
var cookies = gmap.NewUintInterfaceMap()
// 创建一个cookie对象与传入的请求对应
func NewCookie(r *Request) *Cookie {
2017-12-31 12:15:04 +08:00
if r := GetCookie(r.Id); r != nil {
return r
}
c := &Cookie {
data : make(map[string]CookieItem),
2017-12-13 14:13:36 +08:00
domain : defaultDomain(r),
request : r,
response : r.Response,
}
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
}
// 获取一个已经存在的Cookie对象
func GetCookie(requestid int) *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 *Request) string {
2017-12-13 14:13:36 +08:00
return strings.Split(r.Host, ":")[0]
}
// 从请求流中初始化
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(),
}
}
}
// 获取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
}
// 设置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) {
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-13 14:13:36 +08:00
// 查询cookie
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 ""
}
}
return ""
}
// 标记该cookie在对应的域名和路径失效
2017-12-13 14:13:36 +08:00
// 删除cookie的重点是需要通知浏览器客户端cookie已过期
func (c *Cookie) Remove(key, domain, path string) {
c.SetCookie(key, "", domain, path, -86400)
}
2017-12-31 12:15:04 +08:00
// 请求完毕后删除已经存在的Cookie对象
func (c *Cookie) Close() {
cookies.Remove(uint(c.request.Id))
}
// 输出到客户端
func (c *Cookie) Output() {
c.mu.RLock()
defer c.mu.RUnlock()
for k, v := range c.data {
2017-12-13 14:13:36 +08:00
if v.expire == 0 {
continue
}
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),
},
)
}
}