copied the exact logic from net/http package

pull/3379/head
Anshul Sinha 2025-04-01 20:23:40 +05:30
parent 21bde45dc7
commit 0419014f5e
2 changed files with 18 additions and 30 deletions

42
ctx.go
View File

@ -22,7 +22,6 @@ import (
"sync" "sync"
"text/template" "text/template"
"time" "time"
"unicode/utf8"
"github.com/gofiber/utils/v2" "github.com/gofiber/utils/v2"
"github.com/valyala/bytebufferpool" "github.com/valyala/bytebufferpool"
@ -451,39 +450,28 @@ func (c *DefaultCtx) Cookie(cookie *Cookie) {
// The returned value is only valid within the handler. Do not store any references. // The returned value is only valid within the handler. Do not store any references.
// Make copies or use the Immutable setting to use the value outside the Handler. // Make copies or use the Immutable setting to use the value outside the Handler.
func (c *DefaultCtx) Cookies(key string, defaultValue ...string) string { func (c *DefaultCtx) Cookies(key string, defaultValue ...string) string {
value := c.app.getString(c.fasthttp.Request.Header.Cookie(key)) cookieValue := c.app.getString(c.fasthttp.Request.Header.Cookie(key))
// If the value looks like binary data, return it as-is // Parse the cookie value
if len(value) > 0 && !utf8.ValidString(value) { value, ok := c.parseCookieValue(cookieValue)
return value if !ok {
return ""
} }
return defaultString(c.sanitizeCookieValue(value), defaultValue) return value
} }
// sanitizeCookieValue sanitizes a cookie value according to RFC 6265. // parseCookieValue parses a cookie value according to RFC 6265.
// It removes invalid characters from the cookie value, similar to how func (c *DefaultCtx) parseCookieValue(raw string) (value string, ok bool) {
// Go's standard library handles cookie values. // Strip the quotes, if present.
func (c *DefaultCtx) sanitizeCookieValue(v string) string { if len(raw) > 1 && raw[0] == '"' && raw[len(raw)-1] == '"' {
// First, check if all characters are valid. raw = raw[1 : len(raw)-1]
valid := true
for i := 0; i < len(v); i++ {
if !c.validCookieValueByte(v[i]) {
valid = false
break
}
}
// If all characters are valid, return the original string.
if valid {
return v
} }
// Otherwise, build a sanitized string in a byte slice. for i := 0; i < len(raw); i++ {
buf := make([]byte, 0, len(v)) if !c.validCookieValueByte(raw[i]) {
for i := 0; i < len(v); i++ { return "", false
if c.validCookieValueByte(v[i]) {
buf = append(buf, v[i])
} }
} }
return string(buf) return raw, true
} }
// validCookieValueByte reports whether b is a valid byte in a cookie value. // validCookieValueByte reports whether b is a valid byte in a cookie value.

View File

@ -1035,16 +1035,16 @@ func Test_Ctx_Cookies(t *testing.T) {
c.Request().Header.Set("Cookie", "john=doe") c.Request().Header.Set("Cookie", "john=doe")
require.Equal(t, "doe", c.Req().Cookies("john")) require.Equal(t, "doe", c.Req().Cookies("john"))
require.Equal(t, "default", c.Req().Cookies("unknown", "default")) require.Equal(t, "", c.Req().Cookies("unknown", "default"))
c.Request().Header.Set("Cookie", "special=value,with,commas") // commas are allowed c.Request().Header.Set("Cookie", "special=value,with,commas") // commas are allowed
require.Equal(t, "value,with,commas", c.Req().Cookies("special")) require.Equal(t, "value,with,commas", c.Req().Cookies("special"))
c.Request().Header.Set("Cookie", "quotes=value\"with\"quotes") c.Request().Header.Set("Cookie", "quotes=value\"with\"quotes")
require.Equal(t, "valuewithquotes", c.Req().Cookies("quotes")) require.Equal(t, "", c.Req().Cookies("quotes"))
c.Request().Header.Set("Cookie", "backslash=value\\with\\backslash") c.Request().Header.Set("Cookie", "backslash=value\\with\\backslash")
require.Equal(t, "valuewithbackslash", c.Req().Cookies("backslash")) require.Equal(t, "", c.Req().Cookies("backslash"))
} }
// go test -run Test_Ctx_Format // go test -run Test_Ctx_Format