Skip to content

Commit 1d50d41

Browse files
committed
Response: setCookie() supports the Partitioned (CHIPS) attribute
Adds a $partitioned argument to setCookie(). When enabled it appends the Partitioned attribute and forces Secure, which the browser requires for a partitioned cookie. Like $sameSite, the argument lives only on Response, not on the IResponse interface.
1 parent 65cf9f4 commit 1d50d41

2 files changed

Lines changed: 14 additions & 3 deletions

File tree

src/Http/Response.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ public function setCookie(
237237
?bool $secure = null,
238238
?bool $httpOnly = null,
239239
?string $sameSite = null,
240+
bool $partitioned = false,
240241
): static
241242
{
242243
self::checkHeaders();
@@ -250,8 +251,9 @@ public function setCookie(
250251

251252
$seconds = Helpers::expirationToSeconds($expire);
252253
$sameSite ??= self::SameSiteLax;
253-
$secure = $sameSite === self::SameSiteNone
254-
? true // SameSite=None requires the Secure attribute, otherwise the browser rejects the cookie
254+
// both SameSite=None and Partitioned are rejected by the browser without the Secure attribute
255+
$secure = $sameSite === self::SameSiteNone || $partitioned
256+
? true
255257
: $secure ?? $this->cookieSecure;
256258
// the value is raw-url-encoded the same way PHP reads it back from $_COOKIE;
257259
// Max-Age takes precedence over expires (RFC 6265), expires is sent too for ancient clients
@@ -261,7 +263,8 @@ public function setCookie(
261263
. (($domain = $domain ?? ($path ? '' : $this->cookieDomain)) === '' ? '' : '; domain=' . $domain)
262264
. ($secure ? '; secure' : '')
263265
. (($httpOnly ?? true) ? '; HttpOnly' : '')
264-
. '; SameSite=' . $sameSite;
266+
. '; SameSite=' . $sameSite
267+
. ($partitioned ? '; Partitioned' : '');
265268
header('Set-Cookie: ' . $cookie, replace: false);
266269
return $this;
267270
}

tests/Http/Response.setCookie.phpt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,14 @@ $headers = array_values(array_diff(headers_list(), $old, ['Set-Cookie:']));
121121
Assert::same(['Set-Cookie: test=value; path=/; secure; HttpOnly; SameSite=None'], $headers);
122122

123123

124+
// Partitioned (CHIPS) adds the attribute and forces Secure
125+
$response = new Http\Response;
126+
$old = headers_list();
127+
$response->setCookie('test', 'value', null, sameSite: Http\IResponse::SameSiteNone, partitioned: true);
128+
$headers = array_values(array_diff(headers_list(), $old, ['Set-Cookie:']));
129+
Assert::same(['Set-Cookie: test=value; path=/; secure; HttpOnly; SameSite=None; Partitioned'], $headers);
130+
131+
124132
// integer 0 is deprecated, but kept as a session cookie for BC
125133
$response = new Http\Response;
126134
$old = headers_list();

0 commit comments

Comments
 (0)