Буркан с бисквитки
По подразбиране fetch() на Phasis игнорира Set-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) веднъж за всяка стъпка на заявката (така че пренасочванията към друг хост получават актуални бисквитки) и set(url, line) веднъж за всяка заглавка Set-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 — хранилището за бисквитки работи вътре в цикъла за пренасочване на Phasis, върху избрания от вас транспорт.
- Уеб API (WPT) — тестовете на пакета Fetch, които проверяват работата с бисквитки.