İçeriğe geç

Fetch aktarımı

Phasis içindeki varsayılan fetch(), PHP'ın ext-curl uygulamasını kullanır — CURLOPT_FOLLOWLOCATION=false (spesifikasyondaki yönlendirme döngüsü Phasis tarafında çalışır) ve CURLOPT_PROGRESSFUNCTION, AbortSignal değerini izler. Çoğu gömme senaryosu için bu yeterlidir.

Diğer tüm durumlar — proxy'ler, özel DNS, ana uygulamanın mevcut HTTP istemcisi, ağ yalıtımı veya testlerde taklit — için aktarım takılabilir.

Arayüz

PHP
public function setFetchTransport(callable $transport): void

Çağrılabilir işleviniz şunları alır:

PHP
function (array $request, ?\Phasis\Value\JsObject $signal): array

$request ilişkisel bir dizidir:

Anahtar Tür Notlar
method string Zaten büyük harfe dönüştürülmüştür (GET, POST, …)
url string URL ayrıştırıcısı ve yönlendirme zincirinden sonra çözümlenen mutlak URL
headers list<list<string>> [name, value] çiftleri; spesifikasyonun normalleştirdiği büyük-küçük harf biçimi; çok değerli girdiler ayrı çiftlerdir (Set-Cookie vb.)
body string Ham baytlar. Gövdesiz yöntemlerde boş dize.
redirect string "follow" / "error" / "manual" (aktarımınız bunları izlememelidir — yönlendirme döngüsü Phasis içinde çalışır)
timeout int Gerçek zamanlı milisaniye bütçesi. 0 = sınır yok.
credentials string "omit" / "same-origin" / "include" — bilgilendirme amaçlıdır; çerezler setCookieJar() aracılığıyla ayrıca bağlanır.

İstek için sinyal verilmediyse $signal değeri null olur; aksi hâlde aborted ve reason sunan bir JsObject olur. Uzun aktarımlar sırasında bunu yoklayın.

Dönüş biçimi:

PHP
return [
    'status'     => 200,                          // int
    'statusText' => 'OK',                         // string
    'headers'    => [['content-type', 'text/plain'], ['x-custom', '1']],
    'body'       => '...response bytes...',       // string
];

Aktarım hata fırlatırsa Phasis bunu yakalar ve dönüştürür:

  • $e->kind === "aborted" içeren bir Phasis\BuiltIn\Fetch\TransportException → fetch, AbortError DOMException ile reddedilir.
  • kind === "timeout" → iletiyi taşıyan TypeError.
  • kind === "network-error" (varsayılan) → TypeError.
  • Diğer her şey → istisna iletisini içeren TypeError.

Örnekler

Guzzle

PHP
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

$client = new Client(['allow_redirects' => false]);

$engine->setFetchTransport(function (array $req, $signal) use ($client) {
    try {
        $r = $client->request($req['method'], $req['url'], [
            'headers'     => collect($req['headers'])->groupBy(0)->map->pluck(1)->all(),
            'body'        => $req['body'],
            'timeout'     => max(1, $req['timeout'] / 1000.0),
            'http_errors' => false,
        ]);
    } catch (GuzzleException $e) {
        throw new \Phasis\BuiltIn\Fetch\TransportException($e->getMessage(), 'network-error');
    }
    $headers = [];
    foreach ($r->getHeaders() as $name => $values) {
        foreach ($values as $v) {
            $headers[] = [$name, $v];
        }
    }
    return [
        'status'     => $r->getStatusCode(),
        'statusText' => $r->getReasonPhrase(),
        'headers'    => $headers,
        'body'       => (string) $r->getBody(),
    ];
});

Symfony HttpClient

PHP
use Symfony\Component\HttpClient\HttpClient;

$client = HttpClient::create(['max_redirects' => 0]);

$engine->setFetchTransport(function (array $req, $signal) use ($client) {
    $headers = [];
    foreach ($req['headers'] as [$name, $value]) {
        $headers[$name][] = $value;
    }
    $r = $client->request($req['method'], $req['url'], [
        'headers'      => $headers,
        'body'         => $req['body'],
        'timeout'      => $req['timeout'] / 1000.0,
        'max_redirects'=> 0,
    ]);
    return [
        'status'     => $r->getStatusCode(),
        'statusText' => '',
        'headers'    => collect($r->getHeaders(false))
            ->flatMap(fn ($values, $name) => array_map(fn ($v) => [$name, $v], $values))
            ->values()->all(),
        'body'       => $r->getContent(false),
    ];
});

Tümünü reddet

PHP
$engine->setFetchTransport(function () {
    throw new \Phasis\BuiltIn\Fetch\TransportException(
        'network access disabled in this sandbox',
        'network-error',
    );
});

Bu, her fetch() çağrısının TypeError ile reddedilmesini sağlar. Kullanıcı tarafından sağlanan JS değerlerini yalıtmak için kullanışlıdır.

Testler için taklit

PHP
$canned = [
    'https://api.example.com/users' => ['status' => 200, 'body' => '{"users":[]}'],
    'https://api.example.com/404'   => ['status' => 404, 'body' => 'not found'],
];

$engine->setFetchTransport(function (array $req) use ($canned) {
    $r = $canned[$req['url']] ?? ['status' => 500, 'body' => 'no mock'];
    return [
        'status'     => $r['status'],
        'statusText' => $r['status'] === 200 ? 'OK' : 'ERR',
        'headers'    => [['content-type', 'application/json']],
        'body'       => $r['body'],
    ];
});

İlke kancası

Aktarım isteği yürütür; ilke kancası ise isteğin yürütülüp yürütülmeyeceğine karar verir. Bunu yalnızca HTTPS uygulaması, başlık ekleme, URL yeniden yazma, izin listeleri veya kiracı başına kimlik bilgisi bağlama için kullanın.

PHP
public function setFetchPolicy(callable $hook): void

Kanca imzası: function (JsObject $request): ?JsObject. null döndürmek olduğu gibi izin verir. Bir Request döndürmek yeniden yazar. Hata fırlatmak, fetch işlemini fırlatılan hatayla reddeder.

PHP
$allowedHosts = ['api.example.com', 'cdn.example.com'];

$engine->setFetchPolicy(function ($req) use ($allowedHosts) {
    $url = parse_url($req->get('url')->value);
    if (!in_array($url['host'] ?? '', $allowedHosts, true)) {
        throw new \RuntimeException("host not allowed: " . ($url['host'] ?? ''));
    }
    // Inject internal-only auth header
    $req->get('headers')->call('set', 'X-Internal-Token', $secret);
    return null;
});

İlke kancası aktarım çalışmadan önce çalışır — böylece hatalı veya güvenilmeyen bir aktarım bile bunu atlayamaz.

Varsayılan davranış özeti

Konu Varsayılan
Aktarım CurlTransport (PHP ext-curl)
Yönlendirmeler Spesifikasyona göre en fazla 20 yönlendirme izlenir. redirect: "manual", type: "opaqueredirect" içeren yönlendirme Response'unu döndürür.
Zaman aşımı Gerçek zamanlı 30 s, bağlantı için 10 s
TLS doğrulaması CURLOPT_SSL_VERIFYPEER = true (kapatma seçeneği yok — aktarımı değiştirerek geçersiz kılın)
User-Agent Yalnızca ayarlanmamışsa Phasis/0.1 eklenir
Çerezler Hiçbiri saklanmaz. Etkinleştirmek için setCookieJar() kullanın.
İlke kancası Yok. Açıkça reddedilmedikçe tüm isteklere izin verilir.
AbortSignal curl ilerleme geri çağrısı yoklaması aracılığıyla aktarım sırasında dikkate alınır.

Ayrıca bkz.