From 56d60a084efa1b69652b124dab856f214806021d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=2E=20Efe=20=C3=87etin?= Date: Sun, 30 Jun 2024 22:38:46 +0300 Subject: [PATCH] :sparkles: v3 (feature): add CHIPS support to Cookie (#3047) * :sparkles: v3 (feature): add CHIPS support to Cookie * update docs * Update docs/whats_new.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update docs/api/ctx.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: Juan Calderon-Perez <835733+gaby@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- ctx.go | 25 +++++++++++++++---------- ctx_test.go | 5 +++++ docs/api/ctx.md | 41 +++++++++++++++++++++++++++++++---------- docs/whats_new.md | 3 +++ 4 files changed, 54 insertions(+), 20 deletions(-) diff --git a/ctx.go b/ctx.go index aac52dea..9dc018f5 100644 --- a/ctx.go +++ b/ctx.go @@ -175,16 +175,17 @@ type RangeSet struct { // Cookie data for c.Cookie type Cookie struct { - Name string `json:"name"` - Value string `json:"value"` - Path string `json:"path"` - Domain string `json:"domain"` - MaxAge int `json:"max_age"` - Expires time.Time `json:"expires"` - Secure bool `json:"secure"` - HTTPOnly bool `json:"http_only"` - SameSite string `json:"same_site"` - SessionOnly bool `json:"session_only"` + Name string `json:"name"` // The name of the cookie + Value string `json:"value"` // The value of the cookie + Path string `json:"path"` // Specifies a URL path which is allowed to receive the cookie + Domain string `json:"domain"` // Specifies the domain which is allowed to receive the cookie + MaxAge int `json:"max_age"` // The maximum age (in seconds) of the cookie + Expires time.Time `json:"expires"` // The expiration date of the cookie + Secure bool `json:"secure"` // Indicates that the cookie should only be transmitted over a secure HTTPS connection + HTTPOnly bool `json:"http_only"` // Indicates that the cookie is accessible only through the HTTP protocol + SameSite string `json:"same_site"` // Controls whether or not a cookie is sent with cross-site requests + Partitioned bool `json:"partitioned"` // Indicates if the cookie is stored in a partitioned cookie jar + SessionOnly bool `json:"session_only"` // Indicates if the cookie is a session-only cookie } // Views is the interface that wraps the Render function. @@ -437,6 +438,10 @@ func (c *DefaultCtx) Cookie(cookie *Cookie) { fcookie.SetSameSite(fasthttp.CookieSameSiteLaxMode) } + // CHIPS allows to partition cookie jar by top-level site. + // refer: https://developers.google.com/privacy-sandbox/3pcd/chips + fcookie.SetPartitioned(cookie.Partitioned) + c.fasthttp.Response.Header.SetCookie(fcookie) fasthttp.ReleaseCookie(fcookie) } diff --git a/ctx_test.go b/ctx_test.go index 8f13dba1..36673f9e 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -920,6 +920,11 @@ func Test_Ctx_Cookie(t *testing.T) { cookie.MaxAge = 0 c.Cookie(cookie) require.Equal(t, expect, string(c.Response().Header.Peek(HeaderSetCookie))) + + expect = "username=john; path=/; secure; SameSite=None; Partitioned" + cookie.Partitioned = true + c.Cookie(cookie) + require.Equal(t, expect, string(c.Response().Header.Peek(HeaderSetCookie))) } // go test -v -run=^$ -bench=Benchmark_Ctx_Cookie -benchmem -count=4 diff --git a/docs/api/ctx.md b/docs/api/ctx.md index ba903928..0434671c 100644 --- a/docs/api/ctx.md +++ b/docs/api/ctx.md @@ -375,16 +375,17 @@ func (c Ctx) Cookie(cookie *Cookie) ```go type Cookie struct { - Name string `json:"name"` - Value string `json:"value"` - Path string `json:"path"` - Domain string `json:"domain"` - MaxAge int `json:"max_age"` - Expires time.Time `json:"expires"` - Secure bool `json:"secure"` - HTTPOnly bool `json:"http_only"` - SameSite string `json:"same_site"` - SessionOnly bool `json:"session_only"` + Name string `json:"name"` // The name of the cookie + Value string `json:"value"` // The value of the cookie + Path string `json:"path"` // Specifies a URL path which is allowed to receive the cookie + Domain string `json:"domain"` // Specifies the domain which is allowed to receive the cookie + MaxAge int `json:"max_age"` // The maximum age (in seconds) of the cookie + Expires time.Time `json:"expires"` // The expiration date of the cookie + Secure bool `json:"secure"` // Indicates that the cookie should only be transmitted over a secure HTTPS connection + HTTPOnly bool `json:"http_only"` // Indicates that the cookie is accessible only through the HTTP protocol + SameSite string `json:"same_site"` // Controls whether or not a cookie is sent with cross-site requests + Partitioned bool `json:"partitioned"` // Indicates if the cookie is stored in a partitioned cookie jar + SessionOnly bool `json:"session_only"` // Indicates if the cookie is a session-only cookie } ``` @@ -402,6 +403,26 @@ app.Get("/", func(c fiber.Ctx) error { }) ``` +:::info + +Partitioned cookies allow partitioning the cookie jar by top-level site, enhancing user privacy by preventing cookies from being shared across different sites. This feature is particularly useful in scenarios where a user interacts with embedded third-party services that should not have access to the main site's cookies. You can check out [CHIPS](https://developers.google.com/privacy-sandbox/3pcd/chips) for more information. + +::: + +```go title="Example" +app.Get("/", func(c fiber.Ctx) error { + // Create a new partitioned cookie + cookie := new(fiber.Cookie) + cookie.Name = "user_session" + cookie.Value = "abc123" + cookie.Partitioned = true // This cookie will be stored in a separate jar when it's embeded into another website + + // Set the cookie in the response + c.Cookie(cookie) + return c.SendString("Partitioned cookie set") +}) +``` + ## Cookies Get cookie value by key, you could pass an optional default value that will be returned if the cookie key does not exist. diff --git a/docs/whats_new.md b/docs/whats_new.md index c1f7eea7..c34ed4bf 100644 --- a/docs/whats_new.md +++ b/docs/whats_new.md @@ -186,6 +186,9 @@ To enable the routing changes above we had to slightly adjust the signature of t DRAFT section ::: +### New Features + +- Cookie now allows Partitioned cookies for [CHIPS](https://developers.google.com/privacy-sandbox/3pcd/chips) support. CHIPS (Cookies Having Independent Partitioned State) is a feature that improves privacy by allowing cookies to be partitioned by top-level site, mitigating cross-site tracking. ### new methods