code.gitea.io/gitea@v1.19.3/modules/web/middleware/cookie.go (about) 1 // Copyright 2020 The Macaron Authors 2 // Copyright 2020 The Gitea Authors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 5 package middleware 6 7 import ( 8 "net/http" 9 "net/url" 10 "time" 11 12 "code.gitea.io/gitea/modules/setting" 13 ) 14 15 // MaxAge sets the maximum age for a provided cookie 16 func MaxAge(maxAge int) func(*http.Cookie) { 17 return func(c *http.Cookie) { 18 c.MaxAge = maxAge 19 } 20 } 21 22 // Path sets the path for a provided cookie 23 func Path(path string) func(*http.Cookie) { 24 return func(c *http.Cookie) { 25 c.Path = path 26 } 27 } 28 29 // Domain sets the domain for a provided cookie 30 func Domain(domain string) func(*http.Cookie) { 31 return func(c *http.Cookie) { 32 c.Domain = domain 33 } 34 } 35 36 // Secure sets the secure setting for a provided cookie 37 func Secure(secure bool) func(*http.Cookie) { 38 return func(c *http.Cookie) { 39 c.Secure = secure 40 } 41 } 42 43 // HTTPOnly sets the HttpOnly setting for a provided cookie 44 func HTTPOnly(httpOnly bool) func(*http.Cookie) { 45 return func(c *http.Cookie) { 46 c.HttpOnly = httpOnly 47 } 48 } 49 50 // Expires sets the expires and rawexpires for a provided cookie 51 func Expires(expires time.Time) func(*http.Cookie) { 52 return func(c *http.Cookie) { 53 c.Expires = expires 54 c.RawExpires = expires.Format(time.UnixDate) 55 } 56 } 57 58 // SameSite sets the SameSite for a provided cookie 59 func SameSite(sameSite http.SameSite) func(*http.Cookie) { 60 return func(c *http.Cookie) { 61 c.SameSite = sameSite 62 } 63 } 64 65 // NewCookie creates a cookie 66 func NewCookie(name, value string, maxAge int) *http.Cookie { 67 return &http.Cookie{ 68 Name: name, 69 Value: value, 70 HttpOnly: true, 71 Path: setting.SessionConfig.CookiePath, 72 Domain: setting.SessionConfig.Domain, 73 MaxAge: maxAge, 74 Secure: setting.SessionConfig.Secure, 75 } 76 } 77 78 // SetRedirectToCookie convenience function to set the RedirectTo cookie consistently 79 func SetRedirectToCookie(resp http.ResponseWriter, value string) { 80 SetCookie(resp, "redirect_to", value, 81 0, 82 setting.AppSubURL, 83 "", 84 setting.SessionConfig.Secure, 85 true, 86 SameSite(setting.SessionConfig.SameSite)) 87 } 88 89 // DeleteRedirectToCookie convenience function to delete most cookies consistently 90 func DeleteRedirectToCookie(resp http.ResponseWriter) { 91 SetCookie(resp, "redirect_to", "", 92 -1, 93 setting.AppSubURL, 94 "", 95 setting.SessionConfig.Secure, 96 true, 97 SameSite(setting.SessionConfig.SameSite)) 98 } 99 100 // DeleteCSRFCookie convenience function to delete SessionConfigPath cookies consistently 101 func DeleteCSRFCookie(resp http.ResponseWriter) { 102 SetCookie(resp, setting.CSRFCookieName, "", 103 -1, 104 setting.SessionConfig.CookiePath, 105 setting.SessionConfig.Domain) // FIXME: Do we need to set the Secure, httpOnly and SameSite values too? 106 } 107 108 // SetCookie set the cookies. (name, value, lifetime, path, domain, secure, httponly, expires, {sameSite, ...}) 109 // TODO: Copied from gitea.com/macaron/macaron and should be improved after macaron removed. 110 func SetCookie(resp http.ResponseWriter, name, value string, others ...interface{}) { 111 cookie := http.Cookie{} 112 cookie.Name = name 113 cookie.Value = url.QueryEscape(value) 114 115 if len(others) > 0 { 116 switch v := others[0].(type) { 117 case int: 118 cookie.MaxAge = v 119 case int64: 120 cookie.MaxAge = int(v) 121 case int32: 122 cookie.MaxAge = int(v) 123 case func(*http.Cookie): 124 v(&cookie) 125 } 126 } 127 128 cookie.Path = "/" 129 if len(others) > 1 { 130 if v, ok := others[1].(string); ok && len(v) > 0 { 131 cookie.Path = v 132 } else if v, ok := others[1].(func(*http.Cookie)); ok { 133 v(&cookie) 134 } 135 } 136 137 if len(others) > 2 { 138 if v, ok := others[2].(string); ok && len(v) > 0 { 139 cookie.Domain = v 140 } else if v, ok := others[2].(func(*http.Cookie)); ok { 141 v(&cookie) 142 } 143 } 144 145 if len(others) > 3 { 146 switch v := others[3].(type) { 147 case bool: 148 cookie.Secure = v 149 case func(*http.Cookie): 150 v(&cookie) 151 default: 152 if others[3] != nil { 153 cookie.Secure = true 154 } 155 } 156 } 157 158 if len(others) > 4 { 159 if v, ok := others[4].(bool); ok && v { 160 cookie.HttpOnly = true 161 } else if v, ok := others[4].(func(*http.Cookie)); ok { 162 v(&cookie) 163 } 164 } 165 166 if len(others) > 5 { 167 if v, ok := others[5].(time.Time); ok { 168 cookie.Expires = v 169 cookie.RawExpires = v.Format(time.UnixDate) 170 } else if v, ok := others[5].(func(*http.Cookie)); ok { 171 v(&cookie) 172 } 173 } 174 175 if len(others) > 6 { 176 for _, other := range others[6:] { 177 if v, ok := other.(func(*http.Cookie)); ok { 178 v(&cookie) 179 } 180 } 181 } 182 183 resp.Header().Add("Set-Cookie", cookie.String()) 184 } 185 186 // GetCookie returns given cookie value from request header. 187 func GetCookie(req *http.Request, name string) string { 188 cookie, err := req.Cookie(name) 189 if err != nil { 190 return "" 191 } 192 val, _ := url.QueryUnescape(cookie.Value) 193 return val 194 }