Fetch transports
Noklusējuma fetch() Phasis darbojas ar PHP ext-curl — CURLOPT_FOLLOWLOCATION=false (specifikācijas novirzīšanas cikls darbojas Phasis vidē), kur CURLOPT_PROGRESSFUNCTION pārbauda AbortSignal. Lielākajai daļai iegulšanas gadījumu tas ir piemērots.
Visiem pārējiem gadījumiem — starpniekserveriem, pielāgotam DNS, resursdatora lietotnes esošajam HTTP klientam, tīkla izolācijai un testu imitācijām — transportu var nomainīt.
Saskarne
public function setFetchTransport(callable $transport): void
Jūsu izsaucamā funkcija saņem:
function (array $request, ?\Phasis\Value\JsObject $signal): array
$request ir asociatīvs masīvs:
| Atslēga | Tips | Piezīmes |
|---|---|---|
method |
string |
Jau pārveidots uz lielajiem burtiem (GET, POST, …) |
url |
string |
Atrisināts absolūtais URL pēc URL parsētāja un novirzīšanas ķēdes |
headers |
list<list<string>> |
[name, value] pāri; reģistrs normalizēts atbilstoši specifikācijai; vairāku vērtību ieraksti ir atsevišķi pāri (Set-Cookie u. c.) |
body |
string |
Neapstrādāti baiti. Tukša virkne metodēm bez pamatdaļas. |
redirect |
string |
"follow" / "error" / "manual" (jūsu transportam tiem NAV jāseko — novirzīšanas cikls darbojas Phasis) |
timeout |
int |
Sienas pulksteņa laika limits milisekundēs. 0 = bez ierobežojuma. |
credentials |
string |
"omit" / "same-origin" / "include" — informatīvi; sīkdatnes tiek piesaistītas atsevišķi, izmantojot setCookieJar(). |
$signal ir null, ja pieprasījumam nav norādīts signāls; pretējā gadījumā tas ir JsObject, kas atklāj aborted un reason. Ilgu pārsūtīšanas darbību laikā periodiski pārbaudiet to.
Atgriežamā vērtība:
return [
'status' => 200, // int
'statusText' => 'OK', // string
'headers' => [['content-type', 'text/plain'], ['x-custom', '1']],
'body' => '...response bytes...', // string
];
Ja transports izmet kļūdu, Phasis to uztver un pārveido:
- Ja
Phasis\BuiltIn\Fetch\TransportExceptionar$e->kind === "aborted"→fetchtiek noraidīts arAbortError DOMException. kind === "timeout"→TypeErrorar ziņojumu.kind === "network-error"(pēc noklusējuma) →TypeError.- Jebkas cits →
TypeErrorar izņēmuma ziņojumu.
Piemēri
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),
];
});
Visu aizliegt
$engine->setFetchTransport(function () {
throw new \Phasis\BuiltIn\Fetch\TransportException(
'network access disabled in this sandbox',
'network-error',
);
});
Tādējādi katrs fetch() izsaukums tiek noraidīts ar TypeError. Noder lietotāja sniegta JS izolēšanai.
Tests ar aizstājēju
$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'],
];
});
Politikas āķis
Transports izpilda pieprasījumu; politikas āķis nosaka, vai to vispār izpildīt. Izmantojiet to, lai piemērotu tikai HTTPS ierobežojumus, ievietotu galvenes, pārveidotu URL, izveidotu atļauto sarakstu vai piesaistītu katram nomniekam savus akreditācijas datus.
public function setFetchPolicy(callable $hook): void
Āķa signatūra: function (JsObject $request): ?JsObject. Atgriežot null, pieprasījums tiek atļauts bez izmaiņām. Atgriežot Request, pieprasījums tiek pārrakstīts. Izmetot kļūdu, izgūšana tiek noraidīta ar izmesto kļūdu.
$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;
});
Politikas āķis darbojas pirms transporta, tāpēc pat kļūdains vai neuzticams transports to nevar apiet.
Noklusējuma darbības kopsavilkums
| Aspekts | Noklusējums |
|---|---|
| Transports | CurlTransport (PHP ext-curl) |
| Novirzīšana | Saskaņā ar specifikāciju seko ne vairāk kā 20 novirzīšanām. redirect: "manual" atgriež novirzīšanas Response ar type: "opaqueredirect". |
| Taimauts | 30 s sienas pulksteņa laiks, 10 s savienojumam |
| TLS pārbaude | CURLOPT_SSL_VERIFYPEER = true (atteikties no tās nevar — aizstājiet transportu) |
| User-Agent | Phasis/0.1 tiek ievietots tikai tad, ja nav iestatīts |
| Sīkdatnes | Netiek saglabātas. Izmantojiet setCookieJar(), lai tās iespējotu. |
| Politikas āķis | Nav. Visi pieprasījumi ir atļauti, ja vien tie nav skaidri aizliegti. |
| AbortSignal | Pārsūtīšanas laikā tiek ievērots, periodiski pārbaudot curl progresa atzvanīšanas funkciju. |
Skatiet arī
- API atsauce — Fetch āķi — īsa signatūru atsauce.
- Tīmekļa API — pilns Fetch Pack iespēju klāsts.
- Sīkdatņu krātuve — sīkdatņu saglabāšana starp izgūšanas darbībām, izmantojot PHP vai JS krātuves objektu.