github.com/gogf/gf@v1.16.9/net/ghttp/ghttp_server_cookie.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). 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/gogf/gf.
     6  
     7  package ghttp
     8  
     9  import (
    10  	"net/http"
    11  	"time"
    12  )
    13  
    14  // Cookie for HTTP COOKIE management.
    15  type Cookie struct {
    16  	data     map[string]*cookieItem // Underlying cookie items.
    17  	server   *Server                // Belonged HTTP server
    18  	request  *Request               // Belonged HTTP request.
    19  	response *Response              // Belonged HTTP response.
    20  }
    21  
    22  // cookieItem is the item stored in Cookie.
    23  type cookieItem struct {
    24  	*http.Cookie      // Underlying cookie items.
    25  	FromClient   bool // Mark this cookie received from client.
    26  }
    27  
    28  // GetCookie creates or retrieves a cookie object with given request.
    29  // It retrieves and returns an existing cookie object if it already exists with given request.
    30  // It creates and returns a new cookie object if it does not exist with given request.
    31  func GetCookie(r *Request) *Cookie {
    32  	if r.Cookie != nil {
    33  		return r.Cookie
    34  	}
    35  	return &Cookie{
    36  		request: r,
    37  		server:  r.Server,
    38  	}
    39  }
    40  
    41  // init does lazy initialization for cookie object.
    42  func (c *Cookie) init() {
    43  	if c.data != nil {
    44  		return
    45  	}
    46  	c.data = make(map[string]*cookieItem)
    47  	c.response = c.request.Response
    48  	// DO NOT ADD ANY DEFAULT COOKIE DOMAIN!
    49  	//if c.request.Server.GetCookieDomain() == "" {
    50  	//	c.request.Server.GetCookieDomain() = c.request.GetHost()
    51  	//}
    52  	for _, v := range c.request.Cookies() {
    53  		c.data[v.Name] = &cookieItem{
    54  			Cookie:     v,
    55  			FromClient: true,
    56  		}
    57  	}
    58  }
    59  
    60  // Map returns the cookie items as map[string]string.
    61  func (c *Cookie) Map() map[string]string {
    62  	c.init()
    63  	m := make(map[string]string)
    64  	for k, v := range c.data {
    65  		m[k] = v.Value
    66  	}
    67  	return m
    68  }
    69  
    70  // Contains checks if given key exists and not expired in cookie.
    71  func (c *Cookie) Contains(key string) bool {
    72  	c.init()
    73  	if r, ok := c.data[key]; ok {
    74  		if r.Expires.IsZero() || r.Expires.After(time.Now()) {
    75  			return true
    76  		}
    77  	}
    78  	return false
    79  }
    80  
    81  // Set sets cookie item with default domain, path and expiration age.
    82  func (c *Cookie) Set(key, value string) {
    83  	c.SetCookie(
    84  		key,
    85  		value,
    86  		c.request.Server.GetCookieDomain(),
    87  		c.request.Server.GetCookiePath(),
    88  		c.request.Server.GetCookieMaxAge(),
    89  	)
    90  }
    91  
    92  // SetCookie sets cookie item given given domain, path and expiration age.
    93  // The optional parameter <httpOnly> specifies if the cookie item is only available in HTTP,
    94  // which is usually empty.
    95  func (c *Cookie) SetCookie(key, value, domain, path string, maxAge time.Duration, httpOnly ...bool) {
    96  	c.init()
    97  	isHttpOnly := false
    98  	if len(httpOnly) > 0 {
    99  		isHttpOnly = httpOnly[0]
   100  	}
   101  	httpCookie := &http.Cookie{
   102  		Name:     key,
   103  		Value:    value,
   104  		Path:     path,
   105  		Domain:   domain,
   106  		HttpOnly: isHttpOnly,
   107  	}
   108  	if maxAge != 0 {
   109  		httpCookie.Expires = time.Now().Add(maxAge)
   110  	}
   111  	c.data[key] = &cookieItem{
   112  		Cookie: httpCookie,
   113  	}
   114  }
   115  
   116  // SetHttpCookie sets cookie with *http.Cookie.
   117  func (c *Cookie) SetHttpCookie(httpCookie *http.Cookie) {
   118  	c.init()
   119  	c.data[httpCookie.Name] = &cookieItem{
   120  		Cookie: httpCookie,
   121  	}
   122  }
   123  
   124  // GetSessionId retrieves and returns the session id from cookie.
   125  func (c *Cookie) GetSessionId() string {
   126  	return c.Get(c.server.GetSessionIdName())
   127  }
   128  
   129  // SetSessionId sets session id in the cookie.
   130  func (c *Cookie) SetSessionId(id string) {
   131  	c.SetCookie(
   132  		c.server.GetSessionIdName(),
   133  		id,
   134  		c.request.Server.GetCookieDomain(),
   135  		c.request.Server.GetCookiePath(),
   136  		c.server.GetSessionCookieMaxAge(),
   137  	)
   138  }
   139  
   140  // Get retrieves and returns the value with specified key.
   141  // It returns <def> if specified key does not exist and <def> is given.
   142  func (c *Cookie) Get(key string, def ...string) string {
   143  	c.init()
   144  	if r, ok := c.data[key]; ok {
   145  		if r.Expires.IsZero() || r.Expires.After(time.Now()) {
   146  			return r.Value
   147  		}
   148  	}
   149  	if len(def) > 0 {
   150  		return def[0]
   151  	}
   152  	return ""
   153  }
   154  
   155  // Remove deletes specified key and its value from cookie using default domain and path.
   156  // It actually tells the http client that the cookie is expired, do not send it to server next time.
   157  func (c *Cookie) Remove(key string) {
   158  	c.SetCookie(
   159  		key,
   160  		"",
   161  		c.request.Server.GetCookieDomain(),
   162  		c.request.Server.GetCookiePath(),
   163  		-24*time.Hour,
   164  	)
   165  }
   166  
   167  // RemoveCookie deletes specified key and its value from cookie using given domain and path.
   168  // It actually tells the http client that the cookie is expired, do not send it to server next time.
   169  func (c *Cookie) RemoveCookie(key, domain, path string) {
   170  	c.SetCookie(key, "", domain, path, -24*time.Hour)
   171  }
   172  
   173  // Flush outputs the cookie items to client.
   174  func (c *Cookie) Flush() {
   175  	if len(c.data) == 0 {
   176  		return
   177  	}
   178  	for _, v := range c.data {
   179  		if v.FromClient {
   180  			continue
   181  		}
   182  		http.SetCookie(c.response.Writer, v.Cookie)
   183  	}
   184  }