github.com/MontFerret/ferret@v0.18.0/pkg/drivers/cookie.go (about) 1 package drivers 2 3 import ( 4 "context" 5 "fmt" 6 "hash/fnv" 7 "strconv" 8 "strings" 9 "time" 10 11 "github.com/wI2L/jettison" 12 13 "github.com/MontFerret/ferret/pkg/runtime/core" 14 "github.com/MontFerret/ferret/pkg/runtime/values" 15 ) 16 17 type ( 18 // Polyfill for Go 1.10 19 SameSite int 20 21 // HTTPCookie HTTPCookie object 22 HTTPCookie struct { 23 Name string 24 Value string 25 Path string 26 Domain string 27 Expires time.Time 28 MaxAge int 29 Secure bool 30 HTTPOnly bool 31 SameSite SameSite 32 } 33 ) 34 35 const ( 36 SameSiteDefaultMode SameSite = iota + 1 37 SameSiteLaxMode 38 SameSiteStrictMode 39 ) 40 41 func (s SameSite) String() string { 42 switch s { 43 case SameSiteLaxMode: 44 return "Lax" 45 case SameSiteStrictMode: 46 return "Strict" 47 default: 48 return "" 49 } 50 } 51 52 func (c HTTPCookie) Type() core.Type { 53 return HTTPCookieType 54 } 55 56 func (c HTTPCookie) String() string { 57 return fmt.Sprintf("%s=%s", c.Name, c.Value) 58 } 59 60 func (c HTTPCookie) Compare(other core.Value) int64 { 61 if other.Type() != HTTPCookieType { 62 return Compare(HTTPCookieType, other.Type()) 63 } 64 65 oc := other.(HTTPCookie) 66 67 if c.Name != oc.Name { 68 return int64(strings.Compare(c.Name, oc.Name)) 69 } 70 71 if c.Value != oc.Value { 72 return int64(strings.Compare(c.Value, oc.Value)) 73 } 74 75 if c.Path != oc.Path { 76 return int64(strings.Compare(c.Path, oc.Path)) 77 } 78 79 if c.Domain != oc.Domain { 80 return int64(strings.Compare(c.Domain, oc.Domain)) 81 } 82 83 if c.Expires.After(oc.Expires) { 84 return 1 85 } else if c.Expires.Before(oc.Expires) { 86 return -1 87 } 88 89 if c.MaxAge > oc.MaxAge { 90 return 1 91 } else if c.MaxAge < oc.MaxAge { 92 return -1 93 } 94 95 if c.Secure && !oc.Secure { 96 return 1 97 } else if !c.Secure && oc.Secure { 98 return -1 99 } 100 101 if c.HTTPOnly && !oc.HTTPOnly { 102 return 1 103 } else if !c.HTTPOnly && oc.HTTPOnly { 104 return -1 105 } 106 107 if c.SameSite > oc.SameSite { 108 return 1 109 } else if c.SameSite < oc.SameSite { 110 return -1 111 } 112 113 return 0 114 } 115 116 func (c HTTPCookie) Unwrap() interface{} { 117 return c.Value 118 } 119 120 func (c HTTPCookie) Hash() uint64 { 121 h := fnv.New64a() 122 123 h.Write([]byte(c.Type().String())) 124 h.Write([]byte(":")) 125 h.Write([]byte(c.Name)) 126 h.Write([]byte(c.Value)) 127 h.Write([]byte(c.Path)) 128 h.Write([]byte(c.Domain)) 129 h.Write([]byte(c.Expires.String())) 130 h.Write([]byte(strconv.Itoa(c.MaxAge))) 131 h.Write([]byte(fmt.Sprintf("%t", c.Secure))) 132 h.Write([]byte(fmt.Sprintf("%t", c.HTTPOnly))) 133 h.Write([]byte(c.SameSite.String())) 134 135 return h.Sum64() 136 } 137 138 func (c HTTPCookie) Copy() core.Value { 139 cop := c 140 return &cop 141 } 142 143 func (c HTTPCookie) MarshalJSON() ([]byte, error) { 144 v := map[string]interface{}{ 145 "name": c.Name, 146 "value": c.Value, 147 "path": c.Path, 148 "domain": c.Domain, 149 "expires": c.Expires, 150 "max_age": c.MaxAge, 151 "secure": c.Secure, 152 "http_only": c.HTTPOnly, 153 "same_site": c.SameSite.String(), 154 } 155 156 out, err := jettison.MarshalOpts(v, jettison.NoHTMLEscaping()) 157 158 if err != nil { 159 return nil, err 160 } 161 162 return out, err 163 } 164 165 func (c HTTPCookie) GetIn(_ context.Context, path []core.Value) (core.Value, core.PathError) { 166 if len(path) == 0 { 167 return values.None, nil 168 } 169 170 segment := path[0] 171 172 switch values.ToString(segment) { 173 case "name": 174 return values.NewString(c.Name), nil 175 case "value": 176 return values.NewString(c.Value), nil 177 case "path": 178 return values.NewString(c.Path), nil 179 case "domain": 180 return values.NewString(c.Domain), nil 181 case "expires": 182 return values.NewDateTime(c.Expires), nil 183 case "maxAge": 184 return values.NewInt(c.MaxAge), nil 185 case "secure": 186 return values.NewBoolean(c.Secure), nil 187 case "httpOnly": 188 return values.NewBoolean(c.HTTPOnly), nil 189 case "sameSite": 190 return values.NewString(c.SameSite.String()), nil 191 default: 192 return values.None, nil 193 } 194 }