providers/http: Add support for easily getting/setting cookies
This commit is contained in:
		
							parent
							
								
									88ea929288
								
							
						
					
					
						commit
						11dfb795ed
					
				@ -1,16 +1,21 @@
 | 
				
			|||||||
package http
 | 
					package http
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "log"
 | 
				
			||||||
 | 
					import "time"
 | 
				
			||||||
import "net/url"
 | 
					import "net/url"
 | 
				
			||||||
import "net/http"
 | 
					import "net/http"
 | 
				
			||||||
import "html/template"
 | 
					import "html/template"
 | 
				
			||||||
import "git.tebibyte.media/sashakoshka/step"
 | 
					import "git.tebibyte.media/sashakoshka/step"
 | 
				
			||||||
import shttp "git.tebibyte.media/sashakoshka/step/http"
 | 
					import shttp "git.tebibyte.media/sashakoshka/step/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const defaultLifetime = 24 * 7 * time.Hour
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _ step.FuncProvider = new(Provider)
 | 
					var _ step.FuncProvider = new(Provider)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Provider provides HTTP and URL functions.
 | 
					// Provider provides HTTP and URL functions.
 | 
				
			||||||
type Provider struct {
 | 
					type Provider struct {
 | 
				
			||||||
	
 | 
						InsecureCookie bool
 | 
				
			||||||
 | 
						CookieDomain   string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Package fulfills the step.Provider interface.
 | 
					// Package fulfills the step.Provider interface.
 | 
				
			||||||
@ -18,6 +23,22 @@ func (this *Provider) Package () string {
 | 
				
			|||||||
	return "http"
 | 
						return "http"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Provider) Configure (config step.Meta) error {
 | 
				
			||||||
 | 
						if insecureCookieStr := config.Get("http.insecure-cookie"); insecureCookieStr != "" {
 | 
				
			||||||
 | 
							if insecureCookieStr != "true" && insecureCookieStr != "false" {
 | 
				
			||||||
 | 
								return step.ErrTypeMismatch
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							this.InsecureCookie = insecureCookieStr == "true"
 | 
				
			||||||
 | 
							if this.InsecureCookie {
 | 
				
			||||||
 | 
								log.Println("!!! http.insecure-cookie is active, this is not recommended")	
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if cookieDomainStr := config.Get("http.cookie-domain"); cookieDomainStr != "" {
 | 
				
			||||||
 | 
							this.CookieDomain = cookieDomainStr
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FuncMap fulfills the step.FuncProvider interface.
 | 
					// FuncMap fulfills the step.FuncProvider interface.
 | 
				
			||||||
func (this *Provider) FuncMap () template.FuncMap {
 | 
					func (this *Provider) FuncMap () template.FuncMap {
 | 
				
			||||||
	return template.FuncMap {
 | 
						return template.FuncMap {
 | 
				
			||||||
@ -29,6 +50,9 @@ func (this *Provider) FuncMap () template.FuncMap {
 | 
				
			|||||||
		"queryEscape":      url.QueryEscape,
 | 
							"queryEscape":      url.QueryEscape,
 | 
				
			||||||
		"queryUnescape":    url.QueryUnescape,
 | 
							"queryUnescape":    url.QueryUnescape,
 | 
				
			||||||
		"unsafe":           funcUnsafe,
 | 
							"unsafe":           funcUnsafe,
 | 
				
			||||||
 | 
							"getCookie":        this.funcGetCookie,
 | 
				
			||||||
 | 
							"setCookie":        this.funcSetCookie,
 | 
				
			||||||
 | 
							"setCookieExpires": this.funcSetCookieExpires,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -64,3 +88,58 @@ func funcParseForm (req *http.Request) url.Values {
 | 
				
			|||||||
func funcUnsafe(text string)  template.HTML {
 | 
					func funcUnsafe(text string)  template.HTML {
 | 
				
			||||||
	return template.HTML(text)
 | 
						return template.HTML(text)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Provider) funcGetCookie(
 | 
				
			||||||
 | 
						req *http.Request,
 | 
				
			||||||
 | 
						name string,
 | 
				
			||||||
 | 
					) string {
 | 
				
			||||||
 | 
						cookie, err := req.Cookie(name)
 | 
				
			||||||
 | 
						if err != nil { return "" }
 | 
				
			||||||
 | 
						return cookie.Value
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Provider) funcSetCookie(
 | 
				
			||||||
 | 
						res   shttp.WrappedResponseWriter,
 | 
				
			||||||
 | 
						name  string,
 | 
				
			||||||
 | 
						value string,
 | 
				
			||||||
 | 
					) error {
 | 
				
			||||||
 | 
						return this.funcSetCookieExpires(res, name, value, 0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Provider) funcSetCookieExpires(
 | 
				
			||||||
 | 
						res      shttp.WrappedResponseWriter,
 | 
				
			||||||
 | 
						name     string,
 | 
				
			||||||
 | 
						value    string,
 | 
				
			||||||
 | 
						lifetime time.Duration,
 | 
				
			||||||
 | 
					) error {
 | 
				
			||||||
 | 
						if !this.InsecureCookie {
 | 
				
			||||||
 | 
							// https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie
 | 
				
			||||||
 | 
							// __Host- prefix: Cookies with names starting with __Host- are
 | 
				
			||||||
 | 
							// sent only to the host subdomain or domain that set them, and
 | 
				
			||||||
 | 
							// not to any other host. They must be set with the secure flag
 | 
				
			||||||
 | 
							// must be from a secure page (HTTPS), must not have a domain
 | 
				
			||||||
 | 
							// specified, and the path must be /
 | 
				
			||||||
 | 
							name = "__Host-" + name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var expiration time.Time
 | 
				
			||||||
 | 
						if lifetime == 0 {
 | 
				
			||||||
 | 
							expiration = time.Now().Add(defaultLifetime)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							expiration = time.Now().Add(lifetime)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cookie := &http.Cookie {
 | 
				
			||||||
 | 
							Name:     name,
 | 
				
			||||||
 | 
							Value:    value,
 | 
				
			||||||
 | 
							Expires:  expiration,
 | 
				
			||||||
 | 
							SameSite: http.SameSiteStrictMode,
 | 
				
			||||||
 | 
							Path:     "/",
 | 
				
			||||||
 | 
							Domain:   this.CookieDomain,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !this.InsecureCookie {
 | 
				
			||||||
 | 
							cookie.Secure = true
 | 
				
			||||||
 | 
							cookie.HttpOnly = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						underlyingRes := shttp.UnderlyingResponseWriter(res)
 | 
				
			||||||
 | 
						http.SetCookie(underlyingRes, cookie)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user