mirror of
https://gitee.com/johng/gf.git
synced 2024-12-05 05:37:55 +08:00
187 lines
4.8 KiB
Go
187 lines
4.8 KiB
Go
// Copyright GoFrame Author(https://goframe.org). 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.
|
|
|
|
package ghttp
|
|
|
|
import (
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gogf/gf/v2/container/gvar"
|
|
)
|
|
|
|
// Cookie for HTTP COOKIE management.
|
|
type Cookie struct {
|
|
data map[string]*cookieItem // Underlying cookie items.
|
|
server *Server // Belonged HTTP server
|
|
request *Request // Belonged HTTP request.
|
|
response *Response // Belonged HTTP response.
|
|
}
|
|
|
|
// cookieItem is the item stored in Cookie.
|
|
type cookieItem struct {
|
|
*http.Cookie // Underlying cookie items.
|
|
FromClient bool // Mark this cookie received from client.
|
|
}
|
|
|
|
// GetCookie creates or retrieves a cookie object with given request.
|
|
// It retrieves and returns an existing cookie object if it already exists with given request.
|
|
// It creates and returns a new cookie object if it does not exist with given request.
|
|
func GetCookie(r *Request) *Cookie {
|
|
if r.Cookie != nil {
|
|
return r.Cookie
|
|
}
|
|
return &Cookie{
|
|
request: r,
|
|
server: r.Server,
|
|
}
|
|
}
|
|
|
|
// init does lazy initialization for cookie object.
|
|
func (c *Cookie) init() {
|
|
if c.data != nil {
|
|
return
|
|
}
|
|
c.data = make(map[string]*cookieItem)
|
|
c.response = c.request.Response
|
|
// DO NOT ADD ANY DEFAULT COOKIE DOMAIN!
|
|
// if c.request.Server.GetCookieDomain() == "" {
|
|
// c.request.Server.GetCookieDomain() = c.request.GetHost()
|
|
// }
|
|
for _, v := range c.request.Cookies() {
|
|
c.data[v.Name] = &cookieItem{
|
|
Cookie: v,
|
|
FromClient: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
// Map returns the cookie items as 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
|
|
}
|
|
|
|
// Contains checks if given key exists and not expired in cookie.
|
|
func (c *Cookie) Contains(key string) bool {
|
|
c.init()
|
|
if r, ok := c.data[key]; ok {
|
|
if r.Expires.IsZero() || r.Expires.After(time.Now()) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Set sets cookie item with default domain, path and expiration age.
|
|
func (c *Cookie) Set(key, value string) {
|
|
c.SetCookie(
|
|
key,
|
|
value,
|
|
c.request.Server.GetCookieDomain(),
|
|
c.request.Server.GetCookiePath(),
|
|
c.request.Server.GetCookieMaxAge(),
|
|
)
|
|
}
|
|
|
|
// SetCookie sets cookie item with given domain, path and expiration age.
|
|
// The optional parameter `httpOnly` specifies if the cookie item is only available in HTTP,
|
|
// which is usually empty.
|
|
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]
|
|
}
|
|
httpCookie := &http.Cookie{
|
|
Name: key,
|
|
Value: value,
|
|
Path: path,
|
|
Domain: domain,
|
|
HttpOnly: isHttpOnly,
|
|
}
|
|
if maxAge != 0 {
|
|
httpCookie.Expires = time.Now().Add(maxAge)
|
|
}
|
|
c.data[key] = &cookieItem{
|
|
Cookie: httpCookie,
|
|
}
|
|
}
|
|
|
|
// SetHttpCookie sets cookie with *http.Cookie.
|
|
func (c *Cookie) SetHttpCookie(httpCookie *http.Cookie) {
|
|
c.init()
|
|
c.data[httpCookie.Name] = &cookieItem{
|
|
Cookie: httpCookie,
|
|
}
|
|
}
|
|
|
|
// GetSessionId retrieves and returns the session id from cookie.
|
|
func (c *Cookie) GetSessionId() string {
|
|
return c.Get(c.server.GetSessionIdName()).String()
|
|
}
|
|
|
|
// SetSessionId sets session id in the cookie.
|
|
func (c *Cookie) SetSessionId(id string) {
|
|
c.SetCookie(
|
|
c.server.GetSessionIdName(),
|
|
id,
|
|
c.request.Server.GetCookieDomain(),
|
|
c.request.Server.GetCookiePath(),
|
|
c.server.GetSessionCookieMaxAge(),
|
|
)
|
|
}
|
|
|
|
// Get retrieves and returns the value with specified key.
|
|
// It returns `def` if specified key does not exist and `def` is given.
|
|
func (c *Cookie) Get(key string, def ...string) *gvar.Var {
|
|
c.init()
|
|
if r, ok := c.data[key]; ok {
|
|
if r.Expires.IsZero() || r.Expires.After(time.Now()) {
|
|
return gvar.New(r.Value)
|
|
}
|
|
}
|
|
if len(def) > 0 {
|
|
return gvar.New(def[0])
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Remove deletes specified key and its value from cookie using default domain and path.
|
|
// It actually tells the http client that the cookie is expired, do not send it to server next time.
|
|
func (c *Cookie) Remove(key string) {
|
|
c.SetCookie(
|
|
key,
|
|
"",
|
|
c.request.Server.GetCookieDomain(),
|
|
c.request.Server.GetCookiePath(),
|
|
-24*time.Hour,
|
|
)
|
|
}
|
|
|
|
// RemoveCookie deletes specified key and its value from cookie using given domain and path.
|
|
// It actually tells the http client that the cookie is expired, do not send it to server next time.
|
|
func (c *Cookie) RemoveCookie(key, domain, path string) {
|
|
c.SetCookie(key, "", domain, path, -24*time.Hour)
|
|
}
|
|
|
|
// Flush outputs the cookie items to client.
|
|
func (c *Cookie) Flush() {
|
|
if len(c.data) == 0 {
|
|
return
|
|
}
|
|
for _, v := range c.data {
|
|
if v.FromClient {
|
|
continue
|
|
}
|
|
http.SetCookie(c.response.Writer, v.Cookie)
|
|
}
|
|
}
|