Archivio cookie
Per impostazione predefinita, fetch() di Phasis ignora Set-Cookie delle risposte e non invia l'header Cookie nelle richieste. È l'impostazione giusta per l'integrazione lato server: in genere non volete che la risposta di un utente influisca sulla richiesta di un altro.
Se vi servono i cookie — per gestire un flusso che dipende dallo stato della sessione, fare scraping dopo l'accesso o riprodurre il comportamento del browser nei test — collegate un archivio con $engine->setCookieJar($jar).
L'interfaccia
L'archivio può essere qualsiasi oggetto che implementi due metodi:
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
Funzionano sia gli oggetti PHP sia gli JsObject lato JS con membri corrispondenti. Passando null si svuota l'archivio.
Phasis chiama get(url) una volta per ogni passaggio della richiesta (così i reindirizzamenti verso un altro host ricevono cookie aggiornati) e set(url, line) per ogni header Set-Cookie della risposta. La policy dei cookie — corrispondenza del dominio, ambito del percorso, scadenza, SameSite, Secure — è responsabilità dell'archivio, non di Phasis.
Archivio in memoria (test)
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());
È sufficiente per un test di esito positivo, ma ignora Domain=, Path=, Expires= e gli attributi Secure/HttpOnly/SameSite. Non usatelo per operazioni che attraversano un confine di fiducia.
Symfony BrowserKit
Se avete già installato le librerie HTTP di Symfony, BrowserKit\CookieJar gestisce correttamente le policy.
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()));
Archivio lato JS
Se l'archivio si trova lato JS — ad esempio perché volete esaminarlo o inizializzarlo da JavaScript — collegatelo tramite un oggetto 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());
};
$engine->eval($script);
$engine->setCookieJar($engine->eval('$jar'));
Vengono chiamati gli stessi metodi get/set sia che il destinatario sia un oggetto PHP o un JsObject.
Ambito per richiesta
Un archivio appartiene al realm e persiste per ogni fetch() finché non viene svuotato con setCookieJar(null). Per limitarlo a un singolo flusso di richieste, fatelo esplicitamente:
$engine->setCookieJar($jar);
$engine->eval('await runLoginFlow()');
$engine->setCookieJar(null);
Esaminare da PHP
$engine->getCookieJar() restituisce il valore passato, utile per le verifiche nei test.
$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/'));
Vedi anche
- Trasporto fetch — l'archivio cookie opera all'interno del ciclo di reindirizzamento di Phasis, sopra il trasporto installato.
- API web (WPT) — test del Fetch Pack sul comportamento dei cookie.