github.com/zhongdalu/gf@v1.0.0/g/net/ghttp/ghttp_server_cookie.go (about)

     1  // Copyright 2017 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/zhongdalu/gf.
     6  //
     7  // HTTP Cookie管理对象,
     8  // 由于Cookie是和HTTP请求挂钩的,因此被包含到 ghttp 包中进行管理。
     9  
    10  package ghttp
    11  
    12  import (
    13  	"github.com/zhongdalu/gf/g/os/gtime"
    14  	"net/http"
    15  	"time"
    16  )
    17  
    18  // COOKIE对象
    19  type Cookie struct {
    20  	data     map[string]CookieItem // 数据项
    21  	path     string                // 默认的cookie path
    22  	domain   string                // 默认的cookie domain
    23  	maxage   int                   // 默认的cookie maxage
    24  	server   *Server               // 所属Server
    25  	request  *Request              // 所属HTTP请求对象
    26  	response *Response             // 所属HTTP返回对象
    27  }
    28  
    29  // cookie项
    30  type CookieItem struct {
    31  	value    string
    32  	domain   string // 有效域名
    33  	path     string // 有效路径
    34  	expire   int    // 过期时间
    35  	httpOnly bool
    36  }
    37  
    38  // 获取或者创建一个COOKIE对象,与传入的请求对应(延迟初始化)
    39  func GetCookie(r *Request) *Cookie {
    40  	if r.Cookie != nil {
    41  		return r.Cookie
    42  	}
    43  	return &Cookie{
    44  		request: r,
    45  		server:  r.Server,
    46  	}
    47  }
    48  
    49  // 从请求流中初始化,无锁,延迟初始化
    50  func (c *Cookie) init() {
    51  	if c.data == nil {
    52  		c.data = make(map[string]CookieItem)
    53  		c.path = c.request.Server.GetCookiePath()
    54  		c.domain = c.request.Server.GetCookieDomain()
    55  		c.maxage = c.request.Server.GetCookieMaxAge()
    56  		c.response = c.request.Response
    57  		// 如果没有设置COOKIE有效域名,那么设置HOST为默认有效域名
    58  		if c.domain == "" {
    59  			c.domain = c.request.GetHost()
    60  		}
    61  		for _, v := range c.request.Cookies() {
    62  			c.data[v.Name] = CookieItem{
    63  				v.Value, v.Domain, v.Path, v.Expires.Second(), v.HttpOnly,
    64  			}
    65  		}
    66  	}
    67  }
    68  
    69  // 获取所有的Cookie并构造成map[string]string返回.
    70  func (c *Cookie) Map() map[string]string {
    71  	c.init()
    72  	m := make(map[string]string)
    73  	for k, v := range c.data {
    74  		m[k] = v.value
    75  	}
    76  	return m
    77  }
    78  
    79  // 获取SessionId,不存在时则创建
    80  func (c *Cookie) SessionId() string {
    81  	c.init()
    82  	id := c.Get(c.server.GetSessionIdName())
    83  	if id == "" {
    84  		id = makeSessionId()
    85  		c.SetSessionId(id)
    86  	}
    87  	return id
    88  }
    89  
    90  // 获取SessionId,不存在时则创建
    91  func (c *Cookie) MakeSessionId() string {
    92  	c.init()
    93  	id := makeSessionId()
    94  	c.SetSessionId(id)
    95  	return id
    96  }
    97  
    98  // 判断Cookie中是否存在制定键名(并且没有过期)
    99  func (c *Cookie) Contains(key string) bool {
   100  	c.init()
   101  	if r, ok := c.data[key]; ok {
   102  		if r.expire >= 0 {
   103  			return true
   104  		}
   105  	}
   106  	return false
   107  }
   108  
   109  // 设置cookie,使用默认参数
   110  func (c *Cookie) Set(key, value string) {
   111  	c.SetCookie(key, value, c.domain, c.path, c.server.GetCookieMaxAge())
   112  }
   113  
   114  // 设置cookie,带详细cookie参数
   115  func (c *Cookie) SetCookie(key, value, domain, path string, maxAge int, httpOnly ...bool) {
   116  	c.init()
   117  	isHttpOnly := false
   118  	if len(httpOnly) > 0 {
   119  		isHttpOnly = httpOnly[0]
   120  	}
   121  	c.data[key] = CookieItem{
   122  		value, domain, path, int(gtime.Second()) + maxAge, isHttpOnly,
   123  	}
   124  }
   125  
   126  // 获得客户端提交的SessionId
   127  func (c *Cookie) GetSessionId() string {
   128  	return c.Get(c.server.GetSessionIdName())
   129  }
   130  
   131  // 设置SessionId
   132  func (c *Cookie) SetSessionId(id string) {
   133  	c.Set(c.server.GetSessionIdName(), id)
   134  }
   135  
   136  // 查询cookie
   137  func (c *Cookie) Get(key string, def ...string) string {
   138  	c.init()
   139  	if r, ok := c.data[key]; ok {
   140  		if r.expire >= 0 {
   141  			return r.value
   142  		}
   143  	}
   144  	if len(def) > 0 {
   145  		return def[0]
   146  	}
   147  	return ""
   148  }
   149  
   150  // 删除COOKIE,使用默认的domain&path
   151  func (c *Cookie) Remove(key string) {
   152  	c.SetCookie(key, "", c.domain, c.path, -86400)
   153  }
   154  
   155  // 标记该cookie在对应的域名和路径失效
   156  // 删除cookie的重点是需要通知浏览器客户端cookie已过期
   157  func (c *Cookie) RemoveCookie(key, domain, path string) {
   158  	c.SetCookie(key, "", domain, path, -86400)
   159  }
   160  
   161  // 输出到客户端
   162  func (c *Cookie) Output() {
   163  	if len(c.data) == 0 {
   164  		return
   165  	}
   166  	for k, v := range c.data {
   167  		// 只有 expire != 0 的才是服务端在本次请求中设置的cookie
   168  		if v.expire == 0 {
   169  			continue
   170  		}
   171  		http.SetCookie(
   172  			c.response.Writer,
   173  			&http.Cookie{
   174  				Name:     k,
   175  				Value:    v.value,
   176  				Domain:   v.domain,
   177  				Path:     v.path,
   178  				Expires:  time.Unix(int64(v.expire), 0),
   179  				HttpOnly: v.httpOnly,
   180  			},
   181  		)
   182  	}
   183  }