Siirry sisältöön

Evästepurkki

Oletusarvoisesti kohteen Phasis fetch() ohittaa vastauksissa olevat Set-Cookie-tiedot eikä lähetä pyyntöjen mukana Cookie-otsaketta. Se on palvelinpuolen upotuksen kannalta hyvä oletus: tavallisesti et halua yhden käyttäjän vastauksen vaikuttavan toisen käyttäjän pyyntöön.

Jos tarvitset evästeitä esimerkiksi istunnon tilasta riippuvassa työnkulussa, kirjautumisen takaa tietoja keräävässä työkalussa tai selaimen toimintaa testeissä jäljittelevässä koodissa, liitä evästepurkki funktiolla $engine->setCookieJar($jar).

Rajapinta

Evästepurkiksi käy mikä tahansa olio, joka toteuttaa kaksi metodia:

Koodi
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

Sekä PHP-oliot että kohteen JS puolen JsObject-oliot toimivat, jos niissä on vastaavat jäsenet. Välittämällä arvon null purkki tyhjennetään.

Phasis kutsuu metodia get(url) kerran jokaista pyyntöhyppyä kohden (joten uudelleenohjaus toiseen palvelimeen saa käyttöönsä tuoreet evästeet) ja metodia set(url, line) kerran kutakin vastauksen Set-Cookie-otsaketta kohden. Evästepolitiikka, kuten verkkotunnuksen täsmäytys, polun rajaus, vanheneminen, SameSite ja Secure, on purkin vastuulla, ei kohteen Phasis.

Muistissa oleva evästepurkki (testit)

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());

Tämä riittää onnistuvan polun testijärjestelyyn, mutta ohittaa kohteet Domain=, Path=, Expires= sekä määritteet Secure/HttpOnly/SameSite. Älä käytä tätä luottamusrajan ylittävään toimintaan.

Symfony BrowserKit

Jos kohteen Symfony HTTP-kirjastot on jo asennettu, BrowserKit\CookieJar hoitaa käytännöt oikein.

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()));

Kohteen JS puolen purkki

Jos purkki sijaitsee kohteen JS puolella — esimerkiksi koska haluat tarkastella sitä tai lisätä siihen alkutietoja kohteesta JavaScript — sido se JS-oliona:

JavaScript
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'));

Samoja metodeja get/set kutsutaan riippumatta siitä, onko vastaanottaja PHP-olio vai JsObject.

Pyyntökohtainen rajaus

Purkki sijaitsee realmissa ja säilyy jokaisen fetch()-kutsun yli, kunnes se tyhjennetään funktiolla setCookieJar(null). Jos haluat rajata purkin yhteen pyyntöketjuun, tee se erikseen:

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

Tarkastelu kohteesta PHP

$engine->getCookieJar() palauttaa sille välitetyn arvon — hyödyllistä testien tarkistuksissa.

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/'));

Katso myös

  • Fetch-siirtotapa — evästepurkki toimii kohteen Phasis uudelleenohjaussilmukan sisällä ja hyödyntää asennettua siirtotapaa.
  • Verkko-API:t (WPT) — Fetch-paketin testit, jotka kattavat evästeiden toiminnan.