Skip to content

Use Swoole parsed cookies again#233

Merged
ChiragAgg5k merged 3 commits into0.34.xfrom
codex/use-swoole-cookie-parsing
Apr 8, 2026
Merged

Use Swoole parsed cookies again#233
ChiragAgg5k merged 3 commits into0.34.xfrom
codex/use-swoole-cookie-parsing

Conversation

@ChiragAgg5k
Copy link
Copy Markdown
Member

@ChiragAgg5k ChiragAgg5k commented Apr 8, 2026

Summary

This reverts Swoole cookie handling on 0.34.x back to the 0.33.x behavior.

What Changed

  • removed the forced http_parse_cookie => false setting from both Swoole server adapters
  • switched Utopia\Http\Adapter\Swoole\Request::getCookie() back to Swoole's parsed cookie map
  • stopped synthesizing a cookie header from Swoole request state
  • split e2e expectations so FPM still asserts raw Cookie header echoing, while Swoole asserts Request::getCookie() behavior

Why

0.34.x changed Swoole to preserve the raw Cookie header and parse cookies manually. That differs from 0.33.x, where Swoole parsed cookies natively and getCookie() read from $swooleRequest->cookie.

This PR restores the older compatibility model for servers upgrading from 0.33.x to 0.34.x.

Impact

  • Swoole and SwooleCoroutine go back to native parsed-cookie behavior
  • code that depends on raw Cookie header preservation in Swoole will no longer see the 0.34.x behavior
  • FPM behavior is unchanged

Validation

  • vendor/bin/phpunit tests/RequestTest.php tests/ResponseTest.php
  • php -l src/Http/Adapter/Swoole/Request.php
  • php -l src/Http/Adapter/Swoole/Server.php
  • php -l src/Http/Adapter/SwooleCoroutine/Server.php
  • php -l tests/e2e/BaseTest.php
  • php -l tests/e2e/ResponseFPMTest.php
  • php -l tests/e2e/ResponseSwooleTest.php
  • php -l tests/e2e/init.php

@ChiragAgg5k ChiragAgg5k marked this pull request as ready for review April 8, 2026 10:16
@ChiragAgg5k ChiragAgg5k merged commit 995c119 into 0.34.x Apr 8, 2026
5 checks passed
@ChiragAgg5k ChiragAgg5k deleted the codex/use-swoole-cookie-parsing branch April 8, 2026 10:23
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 8, 2026

Greptile Summary

This PR reverts Swoole cookie handling on 0.34.x back to the 0.33.x model: both Swoole server adapters drop the forced http_parse_cookie => false setting, getCookie() reads directly from Swoole's native parsed cookie map ($swooleRequest->cookie), and the e2e test suite is split so FPM asserts raw Cookie header echoing while Swoole asserts per-key getCookie() behaviour.

Key points:

  • The core revert in Request.php and both Server.php files is clean and accomplishes the stated goal.
  • getCookie() applies strtolower() to the lookup key (required because Swoole lowercases all header/cookie names), but the FPM adapter does not — callers using mixed-case cookie names will see different behaviour per adapter. This is restored 0.33.x behaviour, but it's worth documenting.
  • The new Swoole e2e test (testCookie) covers the basic two-cookie case but misses the edge cases (equals in value, no-space separator) that the FPM test exercises. Adding those would provide stronger confidence in Swoole's native parser for less common cookie formats.
  • The PR description mentions a dedicated SwooleRequestTest unit test being added; that file was created and then removed in the final commit ("Remove Swoole adapter unit test"), so the description is slightly ahead of the actual state of the branch.

Confidence Score: 5/5

Safe to merge — all remaining findings are P2 style/test-coverage suggestions that do not block correctness.

The functional change (removing http_parse_cookie => false and switching getCookie() back to the native Swoole map) is straightforward and targeted. Both server adapters are updated consistently. The only concerns are a pre-existing adapter-level case-sensitivity difference and missing edge-case e2e tests for Swoole; neither represents a defect in the code being merged.

src/Http/Adapter/Swoole/Request.php (case-normalisation note) and tests/e2e/ResponseSwooleTest.php (missing edge-case test coverage).

Vulnerabilities

No security concerns identified. The change removes a server-side configuration override and restores reading cookies from Swoole's native parsed map. No user-supplied data is used unsanitised, no secrets are exposed, and there are no injection vectors introduced.

Important Files Changed

Filename Overview
src/Http/Adapter/Swoole/Request.php Reverts getCookie() to read from $swooleRequest->cookie (Swoole's native parsed map) with strtolower() key normalization; creates a case-sensitivity behavioral difference with the FPM adapter.
src/Http/Adapter/Swoole/Server.php Removes the forced http_parse_cookie => false setting, restoring Swoole's default native cookie-parsing behavior. Change is clean.
src/Http/Adapter/SwooleCoroutine/Server.php Same as Swoole/Server.php — removes forced http_parse_cookie => false. Clean removal.
tests/e2e/BaseTest.php Cookie test removed from the shared trait, since FPM and Swoole now have distinct cookie-access semantics. Makes sense.
tests/e2e/ResponseFPMTest.php Adds FPM-specific testCookie() covering raw Cookie header echo with good edge-case coverage (equals in values, no space after semicolon, case-distinct names).
tests/e2e/ResponseSwooleTest.php Adds Swoole-specific testCookie() covering individual getCookie() lookups, but lacks edge-case tests for cookies with = in values, no-space semicolons, and duplicate names with different casing.
tests/e2e/init.php Adds /cookie/:key endpoint for per-cookie lookup alongside the existing /cookies raw-header endpoint. Correct split for adapter-specific tests.

Reviews (1): Last reviewed commit: "Remove Swoole adapter unit test" | Re-trigger Greptile

Comment on lines 272 to 277
public function getCookie(string $key, string $default = ''): string
{
$key = \strtolower($key);

$cookies = \explode(';', $this->getHeader('cookie', ''));
foreach ($cookies as $cookie) {
$cookie = \trim($cookie);
if ($cookie === '') {
continue;
}
$parts = \explode('=', $cookie, 2);
$cookieKey = \trim($parts[0]);
$cookieValue = isset($parts[1]) ? \trim($parts[1]) : '';
if ($cookieKey === $key) {
return $cookieValue;
}
}
$key = strtolower($key);

return $default;
return $this->swoole->cookie[$key] ?? $default;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 getCookie() key normalisation differs from FPM adapter

Swoole's native cookie parser stores cookie names in lowercase (all HTTP header keys are lowercased by Swoole), so the strtolower($key) here correctly normalises lookup. However, FPM\Request::getCookie() performs no such normalisation — it looks up $_COOKIE[$key] with the key exactly as passed.

This means getCookie('MyToken') returns the cookie on Swoole (lowercased lookup matches mytoken) but will miss it on FPM when the cookie was sent as mytoken. The reverse is also true: FPM is case-sensitive while Swoole is case-insensitive. Any application that calls getCookie() with a mixed-case cookie name will behave differently depending on the adapter in use.

This is a pre-existing 0.33.x characteristic being restored, but it may be worth documenting the difference or adding a note to getCookie()'s docblock so callers know to use lowercase keys for portability across adapters.

Comment on lines +19 to +29
{
$headers = ['Cookie: cookie1=value1; cookie2=value2'];

$response = $this->client->call(Client::METHOD_GET, '/cookie/cookie1', $headers);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals('value1', $response['body']);

$response = $this->client->call(Client::METHOD_GET, '/cookie/cookie2', $headers);
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals('value2', $response['body']);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Swoole cookie test missing edge cases that FPM covers

ResponseFPMTest::testCookie() tests several edge cases: cookies with = in the value (cookie1=value1=value2), cookies with no space after the semicolon separator (cookie1=value1;cookie2=value2), and two cookies that differ only in casing (cookie1=v1; Cookie1=v2). None of these are exercised in the Swoole equivalent.

Since the whole point of this PR is to restore Swoole native cookie parsing, it would be valuable to confirm Swoole handles at least the value=with=equals case correctly (i.e. getCookie('cookie1') returns value1=value2), because different cookie parsers handle trailing = splits differently.

Consider adding a test case such as:

$response = $this->client->call(
    Client::METHOD_GET,
    '/cookie/cookie1',
    ['Cookie: cookie1=value1=value2']
);
$this->assertEquals('value1=value2', $response['body']);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants