mirror of
https://github.com/valyala/fasthttp.git
synced 2026-06-13 15:46:49 +03:00
Reduce the size of the Cookie by 32 bytes. (#1866)
Replace the field `bufKV` with two `[]byte` fields and remove the filed `buf`. - Reduce Cookie from **224** to **192** bytes. - In the benchmark tests, although there is no significant performance improvement, it theoretically reduces memory usage by **14.3%**.
This commit is contained in:
@@ -74,9 +74,9 @@ type Cookie struct {
|
||||
domain []byte
|
||||
path []byte
|
||||
|
||||
buf []byte
|
||||
bufK []byte
|
||||
bufV []byte
|
||||
|
||||
bufKV argsKV
|
||||
maxAge int
|
||||
|
||||
sameSite CookieSameSite
|
||||
@@ -156,14 +156,14 @@ func (c *Cookie) Path() []byte {
|
||||
|
||||
// SetPath sets cookie path.
|
||||
func (c *Cookie) SetPath(path string) {
|
||||
c.buf = append(c.buf[:0], path...)
|
||||
c.path = normalizePath(c.path, c.buf)
|
||||
c.bufK = append(c.bufK[:0], path...)
|
||||
c.path = normalizePath(c.path, c.bufK)
|
||||
}
|
||||
|
||||
// SetPathBytes sets cookie path.
|
||||
func (c *Cookie) SetPathBytes(path []byte) {
|
||||
c.buf = append(c.buf[:0], path...)
|
||||
c.path = normalizePath(c.path, c.buf)
|
||||
c.bufK = append(c.bufK[:0], path...)
|
||||
c.path = normalizePath(c.path, c.bufK)
|
||||
}
|
||||
|
||||
// Domain returns cookie domain.
|
||||
@@ -284,11 +284,11 @@ func (c *Cookie) AppendBytes(dst []byte) []byte {
|
||||
dst = append(dst, '=')
|
||||
dst = AppendUint(dst, c.maxAge)
|
||||
} else if !c.expire.IsZero() {
|
||||
c.bufKV.value = AppendHTTPDate(c.bufKV.value[:0], c.expire)
|
||||
c.bufV = AppendHTTPDate(c.bufV[:0], c.expire)
|
||||
dst = append(dst, ';', ' ')
|
||||
dst = append(dst, strCookieExpires...)
|
||||
dst = append(dst, '=')
|
||||
dst = append(dst, c.bufKV.value...)
|
||||
dst = append(dst, c.bufV...)
|
||||
}
|
||||
if len(c.domain) > 0 {
|
||||
dst = appendCookiePart(dst, strCookieDomain, c.domain)
|
||||
@@ -336,8 +336,8 @@ func (c *Cookie) AppendBytes(dst []byte) []byte {
|
||||
// The returned value is valid until the Cookie reused or released (ReleaseCookie).
|
||||
// Do not store references to the returned value. Make copies instead.
|
||||
func (c *Cookie) Cookie() []byte {
|
||||
c.buf = c.AppendBytes(c.buf[:0])
|
||||
return c.buf
|
||||
c.bufK = c.AppendBytes(c.bufK[:0])
|
||||
return c.bufK
|
||||
}
|
||||
|
||||
// String returns cookie representation.
|
||||
@@ -357,8 +357,8 @@ var errNoCookies = errors.New("no cookies found")
|
||||
|
||||
// Parse parses Set-Cookie header.
|
||||
func (c *Cookie) Parse(src string) error {
|
||||
c.buf = append(c.buf[:0], src...)
|
||||
return c.ParseBytes(c.buf)
|
||||
c.bufK = append(c.bufK[:0], src...)
|
||||
return c.ParseBytes(c.bufK)
|
||||
}
|
||||
|
||||
// ParseBytes parses Set-Cookie header.
|
||||
@@ -368,21 +368,20 @@ func (c *Cookie) ParseBytes(src []byte) error {
|
||||
var s cookieScanner
|
||||
s.b = src
|
||||
|
||||
kv := &c.bufKV
|
||||
if !s.next(kv) {
|
||||
if !s.next(&c.bufK, &c.bufV) {
|
||||
return errNoCookies
|
||||
}
|
||||
|
||||
c.key = append(c.key, kv.key...)
|
||||
c.value = append(c.value, kv.value...)
|
||||
c.key = append(c.key, c.bufK...)
|
||||
c.value = append(c.value, c.bufV...)
|
||||
|
||||
for s.next(kv) {
|
||||
if len(kv.key) != 0 {
|
||||
for s.next(&c.bufK, &c.bufV) {
|
||||
if len(c.bufK) != 0 {
|
||||
// Case insensitive switch on first char
|
||||
switch kv.key[0] | 0x20 {
|
||||
switch c.bufK[0] | 0x20 {
|
||||
case 'm':
|
||||
if caseInsensitiveCompare(strCookieMaxAge, kv.key) {
|
||||
maxAge, err := ParseUint(kv.value)
|
||||
if caseInsensitiveCompare(strCookieMaxAge, c.bufK) {
|
||||
maxAge, err := ParseUint(c.bufV)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -390,8 +389,8 @@ func (c *Cookie) ParseBytes(src []byte) error {
|
||||
}
|
||||
|
||||
case 'e': // "expires"
|
||||
if caseInsensitiveCompare(strCookieExpires, kv.key) {
|
||||
v := b2s(kv.value)
|
||||
if caseInsensitiveCompare(strCookieExpires, c.bufK) {
|
||||
v := b2s(c.bufV)
|
||||
// Try the same two formats as net/http
|
||||
// See: https://github.com/golang/go/blob/00379be17e63a5b75b3237819392d2dc3b313a27/src/net/http/cookie.go#L133-L135
|
||||
exptime, err := time.ParseInLocation(time.RFC1123, v, time.UTC)
|
||||
@@ -405,52 +404,52 @@ func (c *Cookie) ParseBytes(src []byte) error {
|
||||
}
|
||||
|
||||
case 'd': // "domain"
|
||||
if caseInsensitiveCompare(strCookieDomain, kv.key) {
|
||||
c.domain = append(c.domain, kv.value...)
|
||||
if caseInsensitiveCompare(strCookieDomain, c.bufK) {
|
||||
c.domain = append(c.domain, c.bufV...)
|
||||
}
|
||||
|
||||
case 'p': // "path"
|
||||
if caseInsensitiveCompare(strCookiePath, kv.key) {
|
||||
c.path = append(c.path, kv.value...)
|
||||
if caseInsensitiveCompare(strCookiePath, c.bufK) {
|
||||
c.path = append(c.path, c.bufV...)
|
||||
}
|
||||
|
||||
case 's': // "samesite"
|
||||
if caseInsensitiveCompare(strCookieSameSite, kv.key) {
|
||||
if len(kv.value) > 0 {
|
||||
if caseInsensitiveCompare(strCookieSameSite, c.bufK) {
|
||||
if len(c.bufV) > 0 {
|
||||
// Case insensitive switch on first char
|
||||
switch kv.value[0] | 0x20 {
|
||||
switch c.bufV[0] | 0x20 {
|
||||
case 'l': // "lax"
|
||||
if caseInsensitiveCompare(strCookieSameSiteLax, kv.value) {
|
||||
if caseInsensitiveCompare(strCookieSameSiteLax, c.bufV) {
|
||||
c.sameSite = CookieSameSiteLaxMode
|
||||
}
|
||||
case 's': // "strict"
|
||||
if caseInsensitiveCompare(strCookieSameSiteStrict, kv.value) {
|
||||
if caseInsensitiveCompare(strCookieSameSiteStrict, c.bufV) {
|
||||
c.sameSite = CookieSameSiteStrictMode
|
||||
}
|
||||
case 'n': // "none"
|
||||
if caseInsensitiveCompare(strCookieSameSiteNone, kv.value) {
|
||||
if caseInsensitiveCompare(strCookieSameSiteNone, c.bufV) {
|
||||
c.sameSite = CookieSameSiteNoneMode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if len(kv.value) != 0 {
|
||||
} else if len(c.bufV) != 0 {
|
||||
// Case insensitive switch on first char
|
||||
switch kv.value[0] | 0x20 {
|
||||
switch c.bufV[0] | 0x20 {
|
||||
case 'h': // "httponly"
|
||||
if caseInsensitiveCompare(strCookieHTTPOnly, kv.value) {
|
||||
if caseInsensitiveCompare(strCookieHTTPOnly, c.bufV) {
|
||||
c.httpOnly = true
|
||||
}
|
||||
|
||||
case 's': // "secure"
|
||||
if caseInsensitiveCompare(strCookieSecure, kv.value) {
|
||||
if caseInsensitiveCompare(strCookieSecure, c.bufV) {
|
||||
c.secure = true
|
||||
} else if caseInsensitiveCompare(strCookieSameSite, kv.value) {
|
||||
} else if caseInsensitiveCompare(strCookieSameSite, c.bufV) {
|
||||
c.sameSite = CookieSameSiteDefaultMode
|
||||
}
|
||||
case 'p': // "partitioned"
|
||||
if caseInsensitiveCompare(strCookiePartitioned, kv.value) {
|
||||
if caseInsensitiveCompare(strCookiePartitioned, c.bufV) {
|
||||
c.partitioned = true
|
||||
}
|
||||
}
|
||||
@@ -507,7 +506,7 @@ func parseRequestCookies(cookies []argsKV, src []byte) []argsKV {
|
||||
s.b = src
|
||||
var kv *argsKV
|
||||
cookies, kv = allocArg(cookies)
|
||||
for s.next(kv) {
|
||||
for s.next(&kv.key, &kv.value) {
|
||||
if len(kv.key) > 0 || len(kv.value) > 0 {
|
||||
cookies, kv = allocArg(cookies)
|
||||
}
|
||||
@@ -519,7 +518,7 @@ type cookieScanner struct {
|
||||
b []byte
|
||||
}
|
||||
|
||||
func (s *cookieScanner) next(kv *argsKV) bool {
|
||||
func (s *cookieScanner) next(key, val *[]byte) bool {
|
||||
b := s.b
|
||||
if len(b) == 0 {
|
||||
return false
|
||||
@@ -532,23 +531,23 @@ func (s *cookieScanner) next(kv *argsKV) bool {
|
||||
case '=':
|
||||
if isKey {
|
||||
isKey = false
|
||||
kv.key = decodeCookieArg(kv.key, b[:i], false)
|
||||
*key = decodeCookieArg(*key, b[:i], false)
|
||||
k = i + 1
|
||||
}
|
||||
case ';':
|
||||
if isKey {
|
||||
kv.key = kv.key[:0]
|
||||
*key = (*key)[:0]
|
||||
}
|
||||
kv.value = decodeCookieArg(kv.value, b[k:i], true)
|
||||
*val = decodeCookieArg(*val, b[k:i], true)
|
||||
s.b = b[i+1:]
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if isKey {
|
||||
kv.key = kv.key[:0]
|
||||
*key = (*key)[:0]
|
||||
}
|
||||
kv.value = decodeCookieArg(kv.value, b[k:], true)
|
||||
*val = decodeCookieArg(*val, b[k:], true)
|
||||
s.b = b[len(b):]
|
||||
return true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user