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…
Reference in New Issue
Block a user