Fetch-transport
Standardtransporten fetch() i Phasis använder PHPs ext-curl — CURLOPT_FOLLOWLOCATION=false (specifikationens omdirigeringsloop körs i Phasis-miljön) medan CURLOPT_PROGRESSFUNCTION kontrollerar AbortSignal. Det fungerar bra för de flesta inbäddningar.
För allt annat — proxyservrar, anpassad DNS, värdappens befintliga HTTP-klient, nätverkssandlådebegränsningar eller mockning i tester — kan transporten bytas ut.
Gränssnittet
public function setFetchTransport(callable $transport): void
Din anropsbara funktion får:
function (array $request, ?\Phasis\Value\JsObject $signal): array
$request är en associativ array:
| Nyckel | Typ | Anmärkningar |
|---|---|---|
method |
string |
Redan konverterad till versaler (GET, POST, …) |
url |
string |
Upplöst absolut URL efter parsning med URL och omdirigeringskedja |
headers |
list<list<string>> |
Par av [name, value]; versaler och gemener normaliseras enligt specifikationen; värden med flera poster blir separata par (Set-Cookie osv.) |
body |
string |
Råa byte. Tom sträng för metoder utan innehåll. |
redirect |
string |
"follow" / "error" / "manual" (din transport ska INTE följa dem — omdirigeringsloopen körs i Phasis) |
timeout |
int |
Tidsbudget enligt väggklockan i millisekunder. 0 = ingen gräns. |
credentials |
string |
"omit" / "same-origin" / "include" — endast information; cookies hanteras separat via setCookieJar(). |
$signal är null om förfrågan saknar signal, annars ett JsObject med aborted och reason. Kontrollera den under långa överföringar.
Returvärde:
return [
'status' => 200, // int
'statusText' => 'OK', // string
'headers' => [['content-type', 'text/plain'], ['x-custom', '1']],
'body' => '...response bytes...', // string
];
Om transporten kastar ett undantag fångar Phasis det och omvandlar det:
- En
Phasis\BuiltIn\Fetch\TransportExceptionmed$e->kind === "aborted"→fetchavvisas medAbortError DOMException. kind === "timeout"→TypeErrormed meddelandet.kind === "network-error"(standard) →TypeError.- Allt annat →
TypeErrormed undantagets meddelande.
Genomarbetade exempel
Guzzle
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
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),
];
});
Neka allt
$engine->setFetchTransport(function () {
throw new \Phasis\BuiltIn\Fetch\TransportException(
'network access disabled in this sandbox',
'network-error',
);
});
Det här gör att varje anrop till fetch() avvisas med TypeError. Användbart för att isolera användartillhandahållen JS i en sandlåda.
Mock för tester
$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'],
];
});
Hook för principer
Transporten hanterar förfrågan; hooken för principer avgör om den alls ska utföras. Använd den för att endast använda HTTPS, lägga till headers, skriva om URL, använda tillåtelselistor eller koppla in autentiseringsuppgifter per klient.
public function setFetchPolicy(callable $hook): void
Hookens signatur: function (JsObject $request): ?JsObject. Om du returnerar null tillåts förfrågan som den är. Om du returnerar en Request skrivs den om. Om du kastar ett undantag avvisas hämtningen med det kastade felet.
$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;
});
Hooken för principer körs före transporten — så inte ens en felaktig eller opålitlig transport kan kringgå den.
Sammanfattning av standardbeteende
| Aspekt | Standard |
|---|---|
| Transport | CurlTransport (PHP ext-curl) |
| Omdirigeringar | Följ upp till 20 enligt specifikationen. redirect: "manual" returnerar omdirigeringens Response med type: "opaqueredirect". |
| Tidsgräns | 30 s enligt väggklockan, 10 s för anslutning |
| Verifiering av TLS | CURLOPT_SSL_VERIFYPEER = true (kan inte väljas bort — åsidosätt genom att byta transport) |
| User-Agent | Phasis/0.1 läggs till endast om den inte redan är inställd |
| Cookies | Inga sparas. Använd setCookieJar() för att aktivera. |
| Hook för principer | Ingen. Alla förfrågningar tillåts om de inte uttryckligen nekas. |
| AbortSignal | Hanteras under överföringen genom en kontroll i curl-förloppsåterkopplingen. |
Se även
- API referens — Fetch-hooks — kortfattad signaturreferens.
- Web APIs — hela Fetch Pack-gränssnittet.
- Cookie-lagring — spara cookies mellan hämtningar med ett PHP- eller JS-lagringsobjekt.