Сховище файлів cookie
За замовчуванням fetch() у Phasis ігнорує Set-Cookie у відповідях і не надсилає заголовок Cookie із запитами. Це правильне значення за замовчуванням для вбудовування на сервері: зазвичай не потрібно, щоб відповідь одного користувача впливала на запит іншого.
Якщо ж вам потрібні файли cookie — для процесу із залежністю від стану сеансу, збирання даних за авторизацією чи імітації поведінки браузера в тестах, — підключіть сховище за допомогою $engine->setCookieJar($jar).
Інтерфейс
Сховищем може бути будь-який об’єкт із двома методами:
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
Підійдуть об’єкти PHP і JS-і JsObject із відповідними властивостями. Передавання null очищує сховище.
Phasis викликає get(url) для кожного переходу запиту (тож після перенаправлення на інший хост використовуються нові файли cookie), а set(url, line) — для кожного заголовка Set-Cookie у відповіді. За політику файлів cookie — зіставлення домену, область дії шляху, термін дії, SameSite, Secure — відповідає сховище, а не Phasis.
Сховище в пам’яті (тести)
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());
Цього достатньо для тесту зі звичайним сценарієм, але тут ігноруються Domain=, Path=, Expires= та атрибути Secure/HttpOnly/SameSite. Не використовуйте це на межі довіри.
Symfony BrowserKit
Якщо у вас уже встановлено бібліотеки HTTP від Symfony, BrowserKit\CookieJar правильно обробляє політику.
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()));
Сховище на стороні JS
Якщо ваше сховище працює на стороні JS — наприклад, щоб переглядати його чи наповнювати з JavaScript, — прив’яжіть його як об’єкт 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'));
Ті самі методи get/set викликаються незалежно від того, чи є отримувач об’єктом PHP, чи JsObject.
Область дії одного запиту
Сховище належить середовищу виконання — воно зберігається між усіма fetch(), доки його не буде очищено через setCookieJar(null). Щоб обмежити сховище одним потоком запитів, зробіть це явно:
$engine->setCookieJar($jar);
$engine->eval('await runLoginFlow()');
$engine->setCookieJar(null);
Перегляд із PHP
$engine->getCookieJar() повертає передане значення — це зручно для перевірок у тестах.
$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/'));
Див. також
- Транспорт Fetch — сховище файлів cookie працює всередині циклу перенаправлень Phasis і взаємодіє з будь-яким підключеним транспортом.
- Веб-API (WPT) — тести пакета Fetch, що перевіряють роботу з файлами cookie.