Skip to content

Commit 2e985d2

Browse files
committed
docs: clarify how to expire cookies with Path/Domain
Remove ExpireCookie method - the existing Cookie() method handles this use case by setting Expires to fasthttp.CookieExpireDelete. Updated documentation to show the recommended approach. Fixes #2878
1 parent e367b5f commit 2e985d2

File tree

5 files changed

+9
-235
lines changed

5 files changed

+9
-235
lines changed

ctx_interface_gen.go

Lines changed: 0 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ctx_test.go

Lines changed: 1 addition & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,7 @@ func Test_Ctx_Cookie_Invalid(t *testing.T) {
12111211
{Name: "i", Value: "b", Domain: "2001:db8::1"}, // ipv6 not allowed
12121212
{Name: "p", Value: "b", Path: "\x00"}, // invalid path byte
12131213
{Name: "e", Value: "b", Expires: time.Date(1500, 1, 1, 0, 0, 0, 0, time.UTC)}, // invalid expires
1214-
// Note: Partitioned without Secure is auto-fixed (Secure=true set automatically per CHIPS spec)
1214+
{Name: "s", Value: "b", Partitioned: true}, // partitioned but not secure
12151215
}
12161216

12171217
for _, invalid := range cases {
@@ -4545,114 +4545,6 @@ func Test_Ctx_ClearCookie(t *testing.T) {
45454545
require.Contains(t, string(c.Response().Header.Peek(HeaderSetCookie)), "test2=; expires=")
45464546
}
45474547

4548-
// go test -run Test_Ctx_ExpireCookie
4549-
func Test_Ctx_ExpireCookie(t *testing.T) {
4550-
t.Parallel()
4551-
4552-
testCases := []struct {
4553-
expectedStrs []string
4554-
notExpectedStrs []string
4555-
name string
4556-
cookie Cookie
4557-
}{
4558-
{
4559-
name: "with path",
4560-
cookie: Cookie{
4561-
Name: "session",
4562-
Path: "/admin",
4563-
},
4564-
expectedStrs: []string{"session=;", "path=/admin", "expires="},
4565-
},
4566-
{
4567-
name: "with domain",
4568-
cookie: Cookie{
4569-
Name: "auth",
4570-
Domain: "example.com",
4571-
},
4572-
expectedStrs: []string{"auth=;", "domain=example.com", "expires="},
4573-
},
4574-
{
4575-
name: "with path and domain",
4576-
cookie: Cookie{
4577-
Name: "token",
4578-
Path: "/api",
4579-
Domain: "example.com",
4580-
},
4581-
expectedStrs: []string{"token=;", "path=/api", "domain=example.com", "expires="},
4582-
},
4583-
{
4584-
name: "with secure and httponly",
4585-
cookie: Cookie{
4586-
Name: "secure_cookie",
4587-
Path: "/",
4588-
Secure: true,
4589-
HTTPOnly: true,
4590-
},
4591-
expectedStrs: []string{"secure_cookie=;", "secure", "HttpOnly", "expires="},
4592-
},
4593-
{
4594-
name: "with SameSite Strict",
4595-
cookie: Cookie{
4596-
Name: "csrf",
4597-
SameSite: CookieSameSiteStrictMode,
4598-
},
4599-
expectedStrs: []string{"csrf=;", "SameSite=Strict", "expires="},
4600-
},
4601-
{
4602-
name: "with SameSite Lax",
4603-
cookie: Cookie{
4604-
Name: "lax_cookie",
4605-
SameSite: CookieSameSiteLaxMode,
4606-
},
4607-
expectedStrs: []string{"lax_cookie=;", "SameSite=Lax", "expires="},
4608-
},
4609-
{
4610-
name: "with SameSite None (should set Secure)",
4611-
cookie: Cookie{
4612-
Name: "cross_site",
4613-
SameSite: CookieSameSiteNoneMode,
4614-
},
4615-
expectedStrs: []string{"cross_site=;", "SameSite=None", "secure", "expires="},
4616-
},
4617-
{
4618-
name: "with Partitioned (should set Secure)",
4619-
cookie: Cookie{
4620-
Name: "partitioned_cookie",
4621-
Partitioned: true,
4622-
},
4623-
expectedStrs: []string{"partitioned_cookie=;", "Partitioned", "secure", "expires="},
4624-
},
4625-
{
4626-
name: "with SameSite Disabled (should not set SameSite)",
4627-
cookie: Cookie{
4628-
Name: "disabled_samesite",
4629-
SameSite: CookieSameSiteDisabled,
4630-
},
4631-
expectedStrs: []string{"disabled_samesite=;", "expires="},
4632-
notExpectedStrs: []string{"SameSite"},
4633-
},
4634-
}
4635-
4636-
for _, tc := range testCases {
4637-
t.Run(tc.name, func(t *testing.T) {
4638-
t.Parallel()
4639-
app := New()
4640-
c := app.AcquireCtx(&fasthttp.RequestCtx{})
4641-
defer app.ReleaseCtx(c)
4642-
4643-
c.Res().ExpireCookie(&tc.cookie)
4644-
setCookie := string(c.Response().Header.Peek(HeaderSetCookie))
4645-
4646-
for _, expected := range tc.expectedStrs {
4647-
require.Contains(t, setCookie, expected)
4648-
}
4649-
for _, notExpected := range tc.notExpectedStrs {
4650-
require.NotContains(t, setCookie, notExpected)
4651-
}
4652-
})
4653-
}
4654-
}
4655-
46564548
// go test -race -run Test_Ctx_Download
46574549
func Test_Ctx_Download(t *testing.T) {
46584550
t.Parallel()

docs/api/ctx.md

Lines changed: 8 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,8 +1760,7 @@ app.Get("/set", func(c fiber.Ctx) error {
17601760
app.Get("/delete", func(c fiber.Ctx) error {
17611761
c.Cookie(&fiber.Cookie{
17621762
Name: "token",
1763-
// Set expiry date to the past
1764-
Expires: time.Now().Add(-(time.Hour * 2)),
1763+
Expires: fasthttp.CookieExpireDelete, // Use fasthttp's built-in constant
17651764
HTTPOnly: true,
17661765
SameSite: "Lax",
17671766
})
@@ -1770,59 +1769,22 @@ app.Get("/delete", func(c fiber.Ctx) error {
17701769
})
17711770
```
17721771

1773-
Alternatively, use `ExpireCookie` for a cleaner approach (see below).
1774-
1775-
### ExpireCookie
1776-
1777-
Expires a cookie by its cookie definition. This is useful when you need to expire a cookie that was set with a specific `Path` or `Domain`. The browser will only clear the cookie if the `Path` and `Domain` attributes match the original cookie.
1778-
1779-
```go title="Signature"
1780-
func (r fiber.Res) ExpireCookie(cookie *fiber.Cookie)
1781-
```
1772+
You can also use `c.Cookie()` to expire cookies with specific `Path` or `Domain` attributes:
17821773

17831774
```go title="Example"
17841775
app.Get("/logout", func(c fiber.Ctx) error {
1785-
// Expire a cookie with specific path
1786-
c.Res().ExpireCookie(&fiber.Cookie{
1787-
Name: "session",
1788-
Path: "/admin",
1789-
})
1790-
1791-
// Expire a cookie with specific domain
1792-
c.Res().ExpireCookie(&fiber.Cookie{
1793-
Name: "auth",
1794-
Domain: "example.com",
1795-
})
1796-
1797-
// Expire a cookie with path, domain, and security flags
1798-
c.Res().ExpireCookie(&fiber.Cookie{
1799-
Name: "token",
1800-
Path: "/api",
1801-
Domain: "example.com",
1802-
Secure: true,
1803-
HTTPOnly: true,
1804-
})
1805-
1806-
// Expire a cookie with SameSite attribute
1807-
c.Res().ExpireCookie(&fiber.Cookie{
1808-
Name: "csrf",
1809-
SameSite: "Strict",
1810-
})
1811-
1812-
// Expire a partitioned cookie (CHIPS)
1813-
c.Res().ExpireCookie(&fiber.Cookie{
1814-
Name: "embedded",
1815-
Partitioned: true,
1776+
// Expire a cookie with path and domain
1777+
c.Cookie(&fiber.Cookie{
1778+
Name: "token",
1779+
Path: "/api",
1780+
Domain: "example.com",
1781+
Expires: fasthttp.CookieExpireDelete,
18161782
})
18171783

18181784
return c.SendStatus(fiber.StatusOK)
18191785
})
18201786
```
18211787

1822-
:::note
1823-
Only the `Name`, `Path`, `Domain`, `Secure`, `HTTPOnly`, `SameSite`, and `Partitioned` fields are used from the Cookie struct. The `Value` and `Expires` fields are overwritten to expire the cookie.
1824-
:::
1825-
18261788
### Cookie
18271789

18281790
Sets a cookie.

res.go

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,6 @@ func (r *DefaultRes) Attachment(filename ...string) {
201201

202202
// ClearCookie expires a specific cookie by key on the client side.
203203
// If no key is provided it expires all cookies that came with the request.
204-
//
205-
// Note: This method does not work for cookies with a specific Domain or Path.
206-
// For those cases, use ExpireCookie to specify the matching attributes.
207204
func (r *DefaultRes) ClearCookie(key ...string) {
208205
request := &r.c.fasthttp.Request
209206
response := &r.c.fasthttp.Response
@@ -218,56 +215,6 @@ func (r *DefaultRes) ClearCookie(key ...string) {
218215
}
219216
}
220217

221-
// ExpireCookie expires a cookie by its cookie definition.
222-
// This is useful when you need to expire a cookie that was set with a specific
223-
// Path or Domain. The browser will only clear the cookie if the Path and Domain
224-
// attributes match the original cookie.
225-
//
226-
// Only the Name, Path, Domain, Secure, HTTPOnly, SameSite, and Partitioned fields are used.
227-
// The Value and Expires fields are overwritten to expire the cookie.
228-
func (r *DefaultRes) ExpireCookie(cookie *Cookie) {
229-
fcookie := fasthttp.AcquireCookie()
230-
defer fasthttp.ReleaseCookie(fcookie)
231-
232-
fcookie.SetKey(cookie.Name)
233-
fcookie.SetValue("")
234-
fcookie.SetExpire(fasthttp.CookieExpireDelete)
235-
236-
if cookie.Path != "" {
237-
fcookie.SetPath(cookie.Path)
238-
}
239-
if cookie.Domain != "" {
240-
fcookie.SetDomain(cookie.Domain)
241-
}
242-
243-
// Handle SameSite attribute
244-
isSecure := cookie.Secure
245-
switch {
246-
case utils.EqualFold(cookie.SameSite, CookieSameSiteStrictMode):
247-
fcookie.SetSameSite(fasthttp.CookieSameSiteStrictMode)
248-
case utils.EqualFold(cookie.SameSite, CookieSameSiteNoneMode):
249-
fcookie.SetSameSite(fasthttp.CookieSameSiteNoneMode)
250-
isSecure = true // SameSite=None requires Secure
251-
case utils.EqualFold(cookie.SameSite, CookieSameSiteLaxMode):
252-
fcookie.SetSameSite(fasthttp.CookieSameSiteLaxMode)
253-
case utils.EqualFold(cookie.SameSite, CookieSameSiteDisabled):
254-
// SameSite explicitly disabled: do not set SameSite attribute
255-
default:
256-
// No SameSite attribute set
257-
}
258-
259-
// Handle Partitioned attribute
260-
if cookie.Partitioned {
261-
fcookie.SetPartitioned(true)
262-
isSecure = true // Partitioned requires Secure
263-
}
264-
265-
fcookie.SetSecure(isSecure)
266-
fcookie.SetHTTPOnly(cookie.HTTPOnly)
267-
268-
r.c.fasthttp.Response.Header.SetCookie(fcookie)
269-
}
270-
271218
// RequestCtx returns *fasthttp.RequestCtx that carries a deadline
272219
// a cancellation signal, and other values across API boundaries.
273220
func (r *DefaultRes) RequestCtx() *fasthttp.RequestCtx {
@@ -302,11 +249,6 @@ func (r *DefaultRes) Cookie(cookie *Cookie) {
302249
sameSite = http.SameSiteLaxMode
303250
}
304251

305-
// Partitioned requires Secure=true per CHIPS spec
306-
if cookie.Partitioned {
307-
cookie.Secure = true
308-
}
309-
310252
// create/validate cookie using net/http
311253
hc := &http.Cookie{
312254
Name: cookie.Name,

res_interface_gen.go

Lines changed: 0 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)