Skip to content

Commit cbbb6dd

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 aa86b9d commit cbbb6dd

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();
@@ -258,8 +259,9 @@ public function setCookie(
258259

259260
$seconds = Helpers::expirationToSeconds($expire);
260261
$sameSite ??= self::SameSiteLax;
261-
$secure = $sameSite === self::SameSiteNone
262-
? true // SameSite=None requires the Secure attribute, otherwise the browser rejects the cookie
262+
// both SameSite=None and Partitioned are rejected by the browser without the Secure attribute
263+
$secure = $sameSite === self::SameSiteNone || $partitioned
264+
? true
263265
: $secure ?? $this->cookieSecure;
264266
// the value is raw-url-encoded the same way PHP reads it back from $_COOKIE;
265267
// Max-Age takes precedence over expires (RFC 6265), expires is sent too for ancient clients
@@ -269,7 +271,8 @@ public function setCookie(
269271
. ($domain === '' ? '' : '; domain=' . $domain)
270272
. ($secure ? '; secure' : '')
271273
. (($httpOnly ?? true) ? '; HttpOnly' : '')
272-
. '; SameSite=' . $sameSite;
274+
. '; SameSite=' . $sameSite
275+
. ($partitioned ? '; Partitioned' : '');
273276
header('Set-Cookie: ' . $cookie, replace: false);
274277
return $this;
275278
}

tests/Http/Response.setCookie.phpt

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

145145

146+
// Partitioned (CHIPS) adds the attribute and forces Secure
147+
$response = new Http\Response;
148+
$old = headers_list();
149+
$response->setCookie('test', 'value', null, sameSite: Http\IResponse::SameSiteNone, partitioned: true);
150+
$headers = array_values(array_diff(headers_list(), $old, ['Set-Cookie:']));
151+
Assert::same(['Set-Cookie: test=value; path=/; secure; HttpOnly; SameSite=None; Partitioned'], $headers);
152+
153+
146154
// integer 0 is deprecated, but kept as a session cookie for BC
147155
$response = new Http\Response;
148156
$old = headers_list();

0 commit comments

Comments
 (0)