code.gitea.io/gitea@v1.22.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 "strings" 11 12 "code.gitea.io/gitea/modules/session" 13 "code.gitea.io/gitea/modules/setting" 14 ) 15 16 // SetRedirectToCookie convenience function to set the RedirectTo cookie consistently 17 func SetRedirectToCookie(resp http.ResponseWriter, value string) { 18 SetSiteCookie(resp, "redirect_to", value, 0) 19 } 20 21 // DeleteRedirectToCookie convenience function to delete most cookies consistently 22 func DeleteRedirectToCookie(resp http.ResponseWriter) { 23 SetSiteCookie(resp, "redirect_to", "", -1) 24 } 25 26 // GetSiteCookie returns given cookie value from request header. 27 func GetSiteCookie(req *http.Request, name string) string { 28 cookie, err := req.Cookie(name) 29 if err != nil { 30 return "" 31 } 32 val, _ := url.QueryUnescape(cookie.Value) 33 return val 34 } 35 36 // SetSiteCookie returns given cookie value from request header. 37 func SetSiteCookie(resp http.ResponseWriter, name, value string, maxAge int) { 38 // Previous versions would use a cookie path with a trailing /. 39 // These are more specific than cookies without a trailing /, so 40 // we need to delete these if they exist. 41 deleteLegacySiteCookie(resp, name) 42 cookie := &http.Cookie{ 43 Name: name, 44 Value: url.QueryEscape(value), 45 MaxAge: maxAge, 46 Path: setting.SessionConfig.CookiePath, 47 Domain: setting.SessionConfig.Domain, 48 Secure: setting.SessionConfig.Secure, 49 HttpOnly: true, 50 SameSite: setting.SessionConfig.SameSite, 51 } 52 resp.Header().Add("Set-Cookie", cookie.String()) 53 } 54 55 // deleteLegacySiteCookie deletes the cookie with the given name at the cookie 56 // path with a trailing /, which would unintentionally override the cookie. 57 func deleteLegacySiteCookie(resp http.ResponseWriter, name string) { 58 if setting.SessionConfig.CookiePath == "" || strings.HasSuffix(setting.SessionConfig.CookiePath, "/") { 59 // If the cookie path ends with /, no legacy cookies will take 60 // precedence, so do nothing. The exception is that cookies with no 61 // path could override other cookies, but it's complicated and we don't 62 // currently handle that. 63 return 64 } 65 66 cookie := &http.Cookie{ 67 Name: name, 68 Value: "", 69 MaxAge: -1, 70 Path: setting.SessionConfig.CookiePath + "/", 71 Domain: setting.SessionConfig.Domain, 72 Secure: setting.SessionConfig.Secure, 73 HttpOnly: true, 74 SameSite: setting.SessionConfig.SameSite, 75 } 76 resp.Header().Add("Set-Cookie", cookie.String()) 77 } 78 79 func init() { 80 session.BeforeRegenerateSession = append(session.BeforeRegenerateSession, func(resp http.ResponseWriter, _ *http.Request) { 81 // Ensure that a cookie with a trailing slash does not take precedence over 82 // the cookie written by the middleware. 83 deleteLegacySiteCookie(resp, setting.SessionConfig.CookieName) 84 }) 85 }