Skip to content

Commit f5baefd

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 8459eca commit f5baefd

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
@@ -109,6 +109,14 @@ $headers = array_values(array_diff(headers_list(), $old, ['Set-Cookie:']));
109109
Assert::same(['Set-Cookie: test=value; path=/; secure; HttpOnly; SameSite=None'], $headers);
110110

111111

112+
// Partitioned (CHIPS) adds the attribute and forces Secure
113+
$response = new Http\Response;
114+
$old = headers_list();
115+
$response->setCookie('test', 'value', null, sameSite: Http\IResponse::SameSiteNone, partitioned: true);
116+
$headers = array_values(array_diff(headers_list(), $old, ['Set-Cookie:']));
117+
Assert::same(['Set-Cookie: test=value; path=/; secure; HttpOnly; SameSite=None; Partitioned'], $headers);
118+
119+
112120
// integer 0 is deprecated, but kept as a session cookie for BC
113121
$response = new Http\Response;
114122
$old = headers_list();

0 commit comments

Comments
 (0)