2019-02-02 16:18:25 +08:00
|
|
|
|
// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
2017-12-29 16:03:30 +08:00
|
|
|
|
//
|
|
|
|
|
// 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,
|
2019-02-02 16:18:25 +08:00
|
|
|
|
// You can obtain one at https://github.com/gogf/gf.
|
2017-12-30 23:49:55 +08:00
|
|
|
|
//
|
|
|
|
|
// HTTP Cookie管理对象,
|
2019-03-11 16:14:55 +08:00
|
|
|
|
// 由于Cookie是和HTTP请求挂钩的,因此被包含到 ghttp 包中进行管理。
|
2017-12-31 18:19:58 +08:00
|
|
|
|
|
2017-12-12 17:25:50 +08:00
|
|
|
|
package ghttp
|
|
|
|
|
|
|
|
|
|
import (
|
2019-06-19 09:06:52 +08:00
|
|
|
|
"net/http"
|
|
|
|
|
"time"
|
2019-07-29 21:01:19 +08:00
|
|
|
|
|
|
|
|
|
"github.com/gogf/gf/os/gtime"
|
2017-12-12 17:25:50 +08:00
|
|
|
|
)
|
|
|
|
|
|
2018-11-16 18:20:09 +08:00
|
|
|
|
// COOKIE对象
|
2017-12-12 17:25:50 +08:00
|
|
|
|
type Cookie struct {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
data map[string]CookieItem // 数据项
|
|
|
|
|
path string // 默认的cookie path
|
|
|
|
|
domain string // 默认的cookie domain
|
|
|
|
|
maxage int // 默认的cookie maxage
|
|
|
|
|
server *Server // 所属Server
|
|
|
|
|
request *Request // 所属HTTP请求对象
|
|
|
|
|
response *Response // 所属HTTP返回对象
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// cookie项
|
|
|
|
|
type CookieItem struct {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
value string
|
|
|
|
|
domain string // 有效域名
|
|
|
|
|
path string // 有效路径
|
|
|
|
|
expire int // 过期时间
|
|
|
|
|
httpOnly bool
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-23 09:20:45 +08:00
|
|
|
|
// 获取或者创建一个COOKIE对象,与传入的请求对应(延迟初始化)
|
2018-04-10 10:32:37 +08:00
|
|
|
|
func GetCookie(r *Request) *Cookie {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
if r.Cookie != nil {
|
|
|
|
|
return r.Cookie
|
|
|
|
|
}
|
|
|
|
|
return &Cookie{
|
|
|
|
|
request: r,
|
|
|
|
|
server: r.Server,
|
|
|
|
|
}
|
2017-12-13 14:13:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-23 09:20:45 +08:00
|
|
|
|
// 从请求流中初始化,无锁,延迟初始化
|
2017-12-12 17:25:50 +08:00
|
|
|
|
func (c *Cookie) init() {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
if c.data == nil {
|
|
|
|
|
c.data = make(map[string]CookieItem)
|
|
|
|
|
c.path = c.request.Server.GetCookiePath()
|
|
|
|
|
c.domain = c.request.Server.GetCookieDomain()
|
|
|
|
|
c.maxage = c.request.Server.GetCookieMaxAge()
|
|
|
|
|
c.response = c.request.Response
|
|
|
|
|
// 如果没有设置COOKIE有效域名,那么设置HOST为默认有效域名
|
|
|
|
|
if c.domain == "" {
|
|
|
|
|
c.domain = c.request.GetHost()
|
|
|
|
|
}
|
|
|
|
|
for _, v := range c.request.Cookies() {
|
|
|
|
|
c.data[v.Name] = CookieItem{
|
|
|
|
|
v.Value, v.Domain, v.Path, v.Expires.Second(), v.HttpOnly,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-23 09:20:45 +08:00
|
|
|
|
// 获取所有的Cookie并构造成map[string]string返回.
|
2018-06-07 09:30:21 +08:00
|
|
|
|
func (c *Cookie) Map() map[string]string {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
c.init()
|
|
|
|
|
m := make(map[string]string)
|
|
|
|
|
for k, v := range c.data {
|
|
|
|
|
m[k] = v.value
|
|
|
|
|
}
|
|
|
|
|
return m
|
2018-06-07 09:30:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-16 18:20:09 +08:00
|
|
|
|
// 获取SessionId,不存在时则创建
|
2017-12-30 23:49:55 +08:00
|
|
|
|
func (c *Cookie) SessionId() string {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
c.init()
|
|
|
|
|
id := c.Get(c.server.GetSessionIdName())
|
|
|
|
|
if id == "" {
|
|
|
|
|
id = makeSessionId()
|
|
|
|
|
c.SetSessionId(id)
|
|
|
|
|
}
|
|
|
|
|
return id
|
2018-11-16 18:20:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-11 16:33:51 +08:00
|
|
|
|
// 获取SessionId,不存在时则创建
|
|
|
|
|
func (c *Cookie) MakeSessionId() string {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
c.init()
|
|
|
|
|
id := makeSessionId()
|
|
|
|
|
c.SetSessionId(id)
|
|
|
|
|
return id
|
2019-03-11 16:33:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-16 18:20:09 +08:00
|
|
|
|
// 判断Cookie中是否存在制定键名(并且没有过期)
|
|
|
|
|
func (c *Cookie) Contains(key string) bool {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
c.init()
|
|
|
|
|
if r, ok := c.data[key]; ok {
|
|
|
|
|
if r.expire >= 0 {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
2017-12-30 23:49:55 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-13 11:36:29 +08:00
|
|
|
|
// 设置cookie,使用默认参数
|
|
|
|
|
func (c *Cookie) Set(key, value string) {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
c.SetCookie(key, value, c.domain, c.path, c.server.GetCookieMaxAge())
|
2017-12-13 11:36:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置cookie,带详细cookie参数
|
2019-06-19 09:06:52 +08:00
|
|
|
|
func (c *Cookie) SetCookie(key, value, domain, path string, maxAge int, httpOnly ...bool) {
|
|
|
|
|
c.init()
|
|
|
|
|
isHttpOnly := false
|
|
|
|
|
if len(httpOnly) > 0 {
|
|
|
|
|
isHttpOnly = httpOnly[0]
|
|
|
|
|
}
|
|
|
|
|
c.data[key] = CookieItem{
|
|
|
|
|
value, domain, path, int(gtime.Second()) + maxAge, isHttpOnly,
|
|
|
|
|
}
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-25 15:20:57 +08:00
|
|
|
|
// 获得客户端提交的SessionId
|
|
|
|
|
func (c *Cookie) GetSessionId() string {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
return c.Get(c.server.GetSessionIdName())
|
2019-02-25 15:20:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-23 09:20:45 +08:00
|
|
|
|
// 设置SessionId
|
|
|
|
|
func (c *Cookie) SetSessionId(id string) {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
c.Set(c.server.GetSessionIdName(), id)
|
2018-11-23 09:20:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-13 14:13:36 +08:00
|
|
|
|
// 查询cookie
|
2019-06-19 09:06:52 +08:00
|
|
|
|
func (c *Cookie) Get(key string, def ...string) string {
|
|
|
|
|
c.init()
|
|
|
|
|
if r, ok := c.data[key]; ok {
|
|
|
|
|
if r.expire >= 0 {
|
|
|
|
|
return r.value
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if len(def) > 0 {
|
|
|
|
|
return def[0]
|
|
|
|
|
}
|
|
|
|
|
return ""
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-26 17:17:11 +08:00
|
|
|
|
// 删除COOKIE,使用默认的domain&path
|
|
|
|
|
func (c *Cookie) Remove(key string) {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
c.SetCookie(key, "", c.domain, c.path, -86400)
|
2019-02-26 17:17:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-30 23:49:55 +08:00
|
|
|
|
// 标记该cookie在对应的域名和路径失效
|
2017-12-13 14:13:36 +08:00
|
|
|
|
// 删除cookie的重点是需要通知浏览器客户端cookie已过期
|
2019-02-26 17:17:11 +08:00
|
|
|
|
func (c *Cookie) RemoveCookie(key, domain, path string) {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
c.SetCookie(key, "", domain, path, -86400)
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 输出到客户端
|
|
|
|
|
func (c *Cookie) Output() {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
if len(c.data) == 0 {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
for k, v := range c.data {
|
|
|
|
|
// 只有 expire != 0 的才是服务端在本次请求中设置的cookie
|
|
|
|
|
if v.expire == 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
http.SetCookie(
|
|
|
|
|
c.response.Writer,
|
|
|
|
|
&http.Cookie{
|
|
|
|
|
Name: k,
|
|
|
|
|
Value: v.value,
|
|
|
|
|
Domain: v.domain,
|
|
|
|
|
Path: v.path,
|
|
|
|
|
Expires: time.Unix(int64(v.expire), 0),
|
|
|
|
|
HttpOnly: v.httpOnly,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
}
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|