symfony / symfony-docs

The Symfony documentation
https://symfony.com/doc
Other
2.15k stars 5.1k forks source link

[HttpClient] fix documentation of Cookies #19947

Closed infinitum11 closed 1 month ago

infinitum11 commented 1 month ago

HttpClient is used for sending HTTP requests, but not for responding to HTTP requests, so the following lines are invalid.

'headers' => [
    'Cookie' => new Cookie('flavor', 'chocolate', strtotime('+1 day')),
    // you can also pass the cookie contents as a string
    'Cookie' => 'flavor=chocolate; expires=Sat, 11 Feb 2023 12:18:13 GMT; Max-Age=86400; path=/'
],

PHP parses and populates the $_COOKIE array as follows which is wrong:

$_COOKIE = [
    "flavor" => "chocolate",
    "expires" => "Sat, 08 Jun 2024 08:34:15 GMT",
    "Max-Age" => "86400",
    "path" => "/",
    "httponly" => "",
    "samesite" => "lax",
];

So, one of the variances is to use the following syntax:

'headers' => [
    'Cookie' => 'foo=bar;baz=zap', 
    // Or an encoded format
    'Cookie' => sprintf("%s=%s", 'foo', rawurlencode('bar'))
],

See:

javiereguiluz commented 1 month ago

@infinitum11 I think I'm missing something in your issue report. The format that you are proposing (xxx=yyy;aaa=bbb;...) is the same as the second format shown in the example. The only difference is that the Symfony example includes some white spaces. Is that the issue? Thanks.

infinitum11 commented 1 month ago

@javiereguiluz Technically they are the same, but semantically they differ. Let me explain.

When sending a cookie from a server to a client, you use the Set-Cookie HTTP Response header. For this, the Symfony\Component\HttpFoundation\Cookie class is used. It specifies attributes like path, domain, SameSite, etc.

However, when sending a cookie from a client to a server, you use the Cookie HTTP Request header (This is the HTTP Client case). There is no path, domain or other attributes, just key=value pair separated by ";".

So, when you set additional HTTP headers this way:

'headers' => [
    'Cookie' => new Cookie('flavor', 'chocolate', strtotime('+1 day')),
    // you can also pass the cookie contents as a string
    'Cookie' => 'flavor=chocolate; expires=Sat, 11 Feb 2023 12:18:13 GMT; Max-Age=86400; path=/'
],

the 6 (six) cookies are sent from the client to a server: flavor, expires, Max-Age, path, httponly, and samesite. Of course, this is not what we expect to receive on the server side.

javiereguiluz commented 1 month ago

@infinitum11 thanks a lot for the detailed explanation. It's clear to me now. I created #19968 to try to fix this. Thanks!