Μετάβαση στο περιεχόμενο

Βάζο cookie

Από προεπιλογή, το fetch() του Phasis αγνοεί τα Set-Cookie από τις αποκρίσεις και δεν στέλνει κεφαλίδα Cookie στα αιτήματα. Αυτή είναι η σωστή προεπιλογή για ενσωμάτωση στην πλευρά του διακομιστή — συνήθως δεν θέλετε η απόκριση ενός χρήστη να επηρεάζει το αίτημα κάποιου άλλου.

Αν θέλετε cookies — για ροή που εξαρτάται από την κατάσταση συνεδρίας, συλλογή δεδομένων πίσω από σύνδεση ή αναπαραγωγή συμπεριφοράς προγράμματος περιήγησης σε δοκιμές — προσαρτήστε ένα jar με το $engine->setCookieJar($jar).

Η διεπαφή

Το 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-side JsObjects με τα αντίστοιχα μέλη. Αν περάσετε null, το jar εκκαθαρίζεται.

Το Phasis καλεί το get(url) μία φορά ανά βήμα αιτήματος (ώστε οι ανακατευθύνσεις σε διαφορετικό host να λαμβάνουν νέα cookies) και το set(url, line) μία φορά για κάθε κεφαλίδα Set-Cookie στην απόκριση. Η πολιτική cookies — αντιστοίχιση domain, περιορισμός διαδρομής, λήξη, SameSite, Secure — είναι ευθύνη του jar, όχι του Phasis.

Jar στη μνήμη (δοκιμές)

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

Αυτό αρκεί για μια δοκιμαστική διάταξη επιτυχούς διαδρομής, αλλά αγνοεί τα Domain=, Path=, Expires= και τα γνωρίσματα Secure/HttpOnly/SameSite. Μην το χρησιμοποιείτε σε περιπτώσεις που διασχίζουν όριο εμπιστοσύνης.

Symfony BrowserKit

Αν έχετε ήδη εγκαταστήσει τις βιβλιοθήκες HTTP του Symfony, το BrowserKit\CookieJar χειρίζεται σωστά την πολιτική.

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

Jar στην πλευρά του JS

Αν το jar σας βρίσκεται στην πλευρά του JS — για παράδειγμα, επειδή θέλετε να το ελέγχετε ή να το αρχικοποιείτε από το JavaScript — συνδέστε το μέσω αντικειμένου JS:

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

Καλούνται οι ίδιες μέθοδοι get/set, είτε ο δέκτης είναι αντικείμενο PHP είτε JsObject.

Εμβέλεια ανά αίτημα

Ένα jar ζει στο realm — διατηρείται σε κάθε fetch() μέχρι να εκκαθαριστεί με setCookieJar(null). Για να περιορίσετε ένα jar σε μία μόνο ροή αιτημάτων, κάντε το ρητά:

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

Επιθεώρηση από το PHP

Το $engine->getCookieJar() επιστρέφει ό,τι του δόθηκε — χρήσιμο για ελέγχους σε δοκιμές.

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

Δείτε επίσης

  • Μεταφορά Fetch — το cookie jar λειτουργεί μέσα στον βρόχο ανακατευθύνσεων του Phasis, πάνω από όποια μεταφορά έχετε εγκαταστήσει.
  • Web APIs (WPT) — οι δοκιμές Fetch Pack που καλύπτουν τη συμπεριφορά των cookies.