
# Cookiepot

Standaard negeert Phasis `fetch()` `Set-Cookie` uit reacties en stuurt het geen `Cookie`-header mee met verzoeken. Dat is de juiste standaardinstelling voor inbedding aan de serverzijde: doorgaans wilt u niet dat de reactie van de ene gebruiker invloed heeft op het verzoek van een andere gebruiker.

Wil je wel cookies gebruiken — bijvoorbeeld voor een flow die afhankelijk is van sessiestatus, scrapen achter een login of het nabootsen van browsergedrag in tests — koppel dan een cookiepot via `$engine->setCookieJar($jar)`.

## De interface

De cookiepot mag elk object zijn dat op twee methoden reageert:

```
get(url: string): string         // returns a "Cookie:" header value, e.g. "sid=abc; pref=dark"
set(url: string, header: string): void   // receives one Set-Cookie line
```

Zowel PHP-objecten als JS-`JsObject`s met de overeenkomstige leden werken. Geef `null` door om de cookiepot te wissen.

Phasis roept `get(url)` één keer aan per verzoekstap (zodat redirects naar een andere host verse cookies krijgen) en `set(url, line)` één keer voor elke `Set-Cookie`-header in de response. Het cookiebeleid — domeinmatching, padbereik, verloop, `SameSite`, `Secure` — valt onder de verantwoordelijkheid van de cookiepot, niet van Phasis.

## Cookiepot in het geheugen (tests)

```php
final class MemoryJar
{
    /** @var array<string, array<string, string>> host → name → "name=value" */
    private array $store = [];

    public function get(string $url): string
    {
        $host = parse_url($url, PHP_URL_HOST) ?? '';
        return implode('; ', $this->store[$host] ?? []);
    }

    public function set(string $url, string $header): void
    {
        $host = parse_url($url, PHP_URL_HOST) ?? '';
        [$nv] = explode(';', $header, 2);
        [$name, $value] = explode('=', trim($nv), 2) + ['', ''];
        if ($name !== '') {
            $this->store[$host][$name] = "$name=$value";
        }
    }
}

$engine->setCookieJar(new MemoryJar());
```

Dit volstaat voor een eenvoudige testfixture, maar houdt geen rekening met `Domain=`, `Path=`, `Expires=` en de attributen `Secure`/`HttpOnly`/`SameSite`. Gebruik dit niet over een vertrouwensgrens heen.

## Symfony BrowserKit

Als de HTTP-bibliotheken van Symfony al zijn geïnstalleerd, regelt `BrowserKit\CookieJar` het beleid correct.

```php
use Symfony\Component\BrowserKit\CookieJar as BrowserCookieJar;
use Symfony\Component\BrowserKit\Cookie;

final class SymfonyJarAdapter
{
    public function __construct(private BrowserCookieJar $jar) {}

    public function get(string $url): string
    {
        $cookies = $this->jar->allValues($url);
        return implode('; ', array_map(
            fn ($n, $v) => "$n=$v",
            array_keys($cookies),
            array_values($cookies),
        ));
    }

    public function set(string $url, string $header): void
    {
        $cookie = Cookie::fromString($header, $url);
        $this->jar->set($cookie);
    }
}

$engine->setCookieJar(new SymfonyJarAdapter(new BrowserCookieJar()));
```

## Cookiepot aan de JS-zijde

Als je cookiepot aan de JS-zijde staat — bijvoorbeeld omdat je deze vanuit JavaScript wilt inspecteren of vullen — koppel je deze via een JS-object:

```js
const jar = new Map();
$jar.get = (url) => Array.from(jar.entries()).map(([k, v]) => `${k}=${v}`).join('; ');
$jar.set = (url, header) => {
  const [nv] = header.split(';');
  const [name, value] = nv.split('=');
  jar.set(name.trim(), value.trim());
};
```

```php
$engine->eval($script);
$engine->setCookieJar($engine->eval('$jar'));
```

Dezelfde methoden `get`/`set` worden aangeroepen, of de ontvanger nu een PHP-object of een `JsObject` is.

## Bereik per verzoek

Een cookiepot hoort bij de realm — deze blijft behouden voor elke `fetch()`, totdat je deze wist met `setCookieJar(null)`. Als je een cookiepot tot één verzoekflow wilt beperken, doe je dat expliciet:

```php
$engine->setCookieJar($jar);
$engine->eval('await runLoginFlow()');
$engine->setCookieJar(null);
```

## Inspecteren vanuit PHP

`$engine->getCookieJar()` geeft terug wat eraan is doorgegeven — handig voor assertions in tests.

```php
$jar = new MemoryJar();
$engine->setCookieJar($jar);
$engine->eval('await fetch("https://api.example.com/login", { method: "POST" })');

assertNotEmpty($engine->getCookieJar()->get('https://api.example.com/'));
```

## Zie ook

- [Fetchtransport](https://phasis.inline0.dev/nl/docs/interop/fetch-transport) — de cookiepot draait **binnen** de redirect-loop van Phasis en wordt toegevoegd aan het transport dat je hebt geïnstalleerd.
- [Web-API's (WPT)](https://phasis.inline0.dev/nl/docs/compatibility/web-apis) — de Fetch Pack-tests voor cookiegedrag.
