Almacén de cookies
De forma predeterminada, Phasis fetch() ignora Set-Cookie de las respuestas y no envía el encabezado Cookie en las solicitudes. Es el comportamiento adecuado para integrarlo en el servidor: normalmente no querrás que la respuesta de un usuario influya en la solicitud de otro.
Si necesitas cookies —para gestionar un flujo que dependa del estado de la sesión, extraer datos tras iniciar sesión o imitar el comportamiento del navegador en pruebas—, añade un almacén con $engine->setCookieJar($jar).
La interfaz
El almacén puede ser cualquier objeto que implemente dos métodos:
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
Funcionan tanto los objetos PHP como los JsObject del lado de JS que tengan los miembros correspondientes. Pasar null vacía el almacén.
Phasis llama a get(url) una vez por cada salto de solicitud (así, las redirecciones a otro host reciben cookies actualizadas) y a set(url, line) una vez por cada encabezado Set-Cookie de la respuesta. La política de cookies —coincidencia de dominio, ámbito de ruta, caducidad, SameSite, Secure— es responsabilidad del almacén, no de Phasis.
Almacén en memoria (pruebas)
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());
Esto basta para una prueba de caso satisfactorio, pero ignora Domain=, Path=, Expires= y los atributos Secure/HttpOnly/SameSite. No lo uses para nada que cruce un límite de confianza.
Symfony BrowserKit
Si ya tienes instaladas las bibliotecas HTTP de Symfony, BrowserKit\CookieJar gestiona correctamente la política.
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()));
Almacén del lado de JS
Si tu almacén está del lado de JS —por ejemplo, porque quieres inspeccionarlo o inicializarlo desde JavaScript—, conéctalo mediante un objeto 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'));
Se llaman los mismos métodos get/set, tanto si quien los recibe es un objeto PHP como si es un JsObject.
Ámbito por solicitud
Un almacén pertenece al entorno: persiste en cada fetch() hasta que se vacía con setCookieJar(null). Para limitarlo a un solo flujo de solicitudes, hazlo explícitamente:
$engine->setCookieJar($jar);
$engine->eval('await runLoginFlow()');
$engine->setCookieJar(null);
Inspección desde PHP
$engine->getCookieJar() devuelve lo que se le pasó, lo que resulta útil para hacer comprobaciones en pruebas.
$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/'));
Véase también
- Transporte Fetch — el almacén de cookies funciona dentro del bucle de redirecciones de Phasis y se integra con el transporte que hayas instalado.
- API web (WPT) — pruebas del paquete Fetch que cubren el comportamiento de las cookies.