ghttp_server_cookie.go 4.7 KB

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