mirror of
https://gitee.com/johng/gf.git
synced 2024-12-03 04:37:49 +08:00
166 lines
4.0 KiB
Go
166 lines
4.0 KiB
Go
// Copyright 2017 gf Author(https://github.com/gogf/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://github.com/gogf/gf.
|
||
//
|
||
// HTTP Cookie管理对象,
|
||
// 由于Cookie是和HTTP请求挂钩的,因此被包含到 ghttp 包中进行管理。
|
||
|
||
package ghttp
|
||
|
||
import (
|
||
"net/http"
|
||
"time"
|
||
|
||
"github.com/gogf/gf/os/gtime"
|
||
)
|
||
|
||
// COOKIE对象,非并发安全。
|
||
type Cookie struct {
|
||
data map[string]CookieItem // 数据项
|
||
path string // 默认的cookie path
|
||
domain string // 默认的cookie domain
|
||
maxage time.Duration // 默认的cookie maxage
|
||
server *Server // 所属Server
|
||
request *Request // 所属HTTP请求对象
|
||
response *Response // 所属HTTP返回对象
|
||
}
|
||
|
||
// cookie项
|
||
type CookieItem struct {
|
||
value string
|
||
domain string // 有效域名
|
||
path string // 有效路径
|
||
expireAt int64 // 过期时间
|
||
httpOnly bool
|
||
}
|
||
|
||
// 获取或者创建一个COOKIE对象,与传入的请求对应(延迟初始化)
|
||
func GetCookie(r *Request) *Cookie {
|
||
if r.Cookie != nil {
|
||
return r.Cookie
|
||
}
|
||
return &Cookie{
|
||
request: r,
|
||
server: r.Server,
|
||
}
|
||
}
|
||
|
||
// 从请求流中初始化,无锁,延迟初始化
|
||
func (c *Cookie) init() {
|
||
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, int64(v.Expires.Second()), v.HttpOnly,
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 获取所有的Cookie并构造成map[string]string返回.
|
||
func (c *Cookie) Map() map[string]string {
|
||
c.init()
|
||
m := make(map[string]string)
|
||
for k, v := range c.data {
|
||
m[k] = v.value
|
||
}
|
||
return m
|
||
}
|
||
|
||
// 判断Cookie中是否存在制定键名(并且没有过期)
|
||
func (c *Cookie) Contains(key string) bool {
|
||
c.init()
|
||
if r, ok := c.data[key]; ok {
|
||
if r.expireAt >= 0 {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
// 设置cookie,使用默认参数
|
||
func (c *Cookie) Set(key, value string) {
|
||
c.SetCookie(key, value, c.domain, c.path, c.server.GetCookieMaxAge())
|
||
}
|
||
|
||
// 设置cookie,带详细cookie参数
|
||
func (c *Cookie) SetCookie(key, value, domain, path string, maxAge time.Duration, httpOnly ...bool) {
|
||
c.init()
|
||
isHttpOnly := false
|
||
if len(httpOnly) > 0 {
|
||
isHttpOnly = httpOnly[0]
|
||
}
|
||
c.data[key] = CookieItem{
|
||
value, domain, path, gtime.Second() + int64(maxAge.Seconds()), isHttpOnly,
|
||
}
|
||
}
|
||
|
||
// 获得客户端提交的SessionId
|
||
func (c *Cookie) GetSessionId() string {
|
||
return c.Get(c.server.GetSessionIdName())
|
||
}
|
||
|
||
// 设置SessionId到Cookie中
|
||
func (c *Cookie) SetSessionId(id string) {
|
||
c.Set(c.server.GetSessionIdName(), id)
|
||
}
|
||
|
||
// 查询cookie
|
||
func (c *Cookie) Get(key string, def ...string) string {
|
||
c.init()
|
||
if r, ok := c.data[key]; ok {
|
||
if r.expireAt >= 0 {
|
||
return r.value
|
||
}
|
||
}
|
||
if len(def) > 0 {
|
||
return def[0]
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// 删除COOKIE,使用默认的domain&path
|
||
func (c *Cookie) Remove(key string) {
|
||
c.SetCookie(key, "", c.domain, c.path, -86400)
|
||
}
|
||
|
||
// 标记该cookie在对应的域名和路径失效
|
||
// 删除cookie的重点是需要通知浏览器客户端cookie已过期
|
||
func (c *Cookie) RemoveCookie(key, domain, path string) {
|
||
c.SetCookie(key, "", domain, path, -86400)
|
||
}
|
||
|
||
// 输出到客户端
|
||
func (c *Cookie) Output() {
|
||
if len(c.data) == 0 {
|
||
return
|
||
}
|
||
for k, v := range c.data {
|
||
// 只有 expire != 0 的才是服务端在本次请求中设置的cookie
|
||
if v.expireAt == 0 {
|
||
continue
|
||
}
|
||
http.SetCookie(
|
||
c.response.Writer,
|
||
&http.Cookie{
|
||
Name: k,
|
||
Value: v.value,
|
||
Domain: v.domain,
|
||
Path: v.path,
|
||
Expires: time.Unix(v.expireAt, 0),
|
||
HttpOnly: v.httpOnly,
|
||
},
|
||
)
|
||
}
|
||
}
|