---
title: "Klienti tretích strán — Safe Fetch for Laravel | Roundly"
description: "Ochrana vlastného klienta Guzzle či PSR-18 knižnice cez guzzleClient() a handlerStack(), s limitmi a testovaním, plus poznámky k laravel/mcp a laravel/ai."
url: https://roundly-consulting.com/sk/open-source/navody/safe-fetch-for-laravel/klienti-tretich-stran
language: sk
---

[Všetky balíky](https://roundly-consulting.com/sk/open-source.md)

[Safe Fetch for Laravel](https://roundly-consulting.com/sk/open-source/navody/safe-fetch-for-laravel.md)

# Klienti tretích strán

Http::safe() chráni požiadavku, ktorú zostavíte vy. Knižnica, ktorá posiela požiadavky sama, potrebuje namiesto toho jedno z tohto:

| Knižnica… | Použite | Chránené |
| --- | --- | --- |
| prijme hotového klienta Guzzle alebo klienta PSR-18 (Client z Guzzle je oboje) | `SafeFetch::guzzleClient(array $config = [], ?DestinationPolicy $policy = null)` | áno |
| zostavuje si vlastného klienta Guzzle a dovolí odovzdať handler | `SafeFetch::handlerStack(?DestinationPolicy $policy = null)` | áno |
| posiela cez fasádu Http z Laravelu vo vlastnom kóde | žiadny háčik — podedíte triedu, ktorá požiadavku zostavuje, alebo URL načítate sami (pozrite poznámky ku knižniciam) | len tam, kde volanie nahradíte |

Obe metódy overia, pripnú a skontrolujú každý krok presne ako Http::safe(): ten istý middleware ochrany, ten istý curl handler, ktorý ochrana vlastní, presmerovania sledované len podľa pravidiel, kontrola primary\_ip po odoslaní a cookie jar pre každý krok. Ani jedna neuvoľňuje Http::safe(): setClient() alebo voľba handler na chránenej požiadavke Laravelu sa stále odmietne. Bez curl obe odmietnu s cannot\_pin.

## Chránený klient Guzzle

```php
use RoundlyConsulting\SafeFetch\Facades\SafeFetch;

$client = SafeFetch::guzzleClient(['base_uri' => 'https://api.partner.example/', 'timeout' => 10]);

$response = $client->get('v1/items');
$client->post('v1/hooks', ['json' => ['url' => $tenantUrl]]);

// Redirects are the guard's: turn them on in the policy, never in the client config
$client = SafeFetch::guzzleClient(policy: SafeFetch::policy()->followRedirects());
```

$config je konfigurácia klienta Guzzle. Dva kľúče sa odmietnu s UnsafeRequestOptions, pretože by požiadavky poslali mimo ochrany:

- handler — nahradil by chránený zásobník. Middleware namiesto toho pridajte do SafeFetch::handlerStack().
- allow\_redirects s inou hodnotou než false — presmerovania sleduje ochrana sama a overí každý krok. Zapnite ich v pravidlách.

```php
SafeFetch::guzzleClient(['handler' => $myStack]);         // UnsafeRequestOptions — push middleware onto handlerStack() instead
SafeFetch::guzzleClient(['allow_redirects' => true]);     // UnsafeRequestOptions — use the policy's followRedirects()
```

Každá iná voľba klienta funguje ako pri obyčajnom klientovi Guzzle: http\_errors (predvolene zapnuté, takže 4xx alebo 5xx vyhodí ClientException či ServerException z Guzzle), headers, auth, cookies => true, connect\_timeout, on\_stats, asynchrónne požiadavky a GuzzleHttpPool. Pri každej požiadavke ochrana odmietne to isté ako pri Http::safe(): proxy, ktorú ste zvolili (proxy z prostredia sa obchádzajú), surovú voľbu curl mimo zoznamu povolených, transport\_sharing a sink pri nastavenom limite tela. Odmietnutie ochranou je DestinationRejected alebo DestinationUnavailable, vyhodené bez zmeny — pri asynchrónnej požiadavke ako zamietnutý promise.

## Zásobník handlerov pre klienta, ktorého si zostaví knižnica

```php
use GuzzleHttp\Client;
use RoundlyConsulting\SafeFetch\Facades\SafeFetch;

$stack = SafeFetch::handlerStack(SafeFetch::policy()->allowHosts(['*.partner.example']));

$client = new Client(['handler' => $stack, 'base_uri' => 'https://api.partner.example/']);
```

Je to ten istý zásobník, cez ktorý ide chránená požiadavka Laravelu — vlastný curl handler ochrany, middleware ochrany, stub a recorder Laravelu — a nad ním tenká vrstva, ktorá predvolené nastavenia klienta Guzzle prevedie na to, s čím ochrana pracuje:

- Presmerovania vypnuté — obyčajný klient Guzzle sleduje presmerovania sám. Na tomto zásobníku dostane presmerovanie späť, ibaže ho sledujú pravidlá (followRedirects()), pričom sa každý krok overí a pripne.
- Cookie jar klienta sa odovzdá ochrane, ktorá ho uplatní pri každom kroku tak, ako to robia vlastné presmerovania Guzzle.
- Middleware, ktorý knižnica do zásobníka pridá cez push, je vnútri ochrany, tesne nad jej handlerom: beží pri každom kroku a požiadavku, ktorú po overení presmeruje (iná URL, hlavička Host), ochrana odmietne s cannot\_pin skôr, než sa čokoľvek vytočí. Middleware pridaný cez unshift() je mimo nej a beží raz na volanie.
- Http::globalMiddleware() platí ako pri Http::safe(); Http::globalOptions() nie — platia vlastné voľby klienta. handler v Http::globalOptions() sa odmietne s UnsafeRequestOptions.

## Limity

Obe metódy rešpektujú limity z pravidiel, takže request.max\_bytes a request.timeout platia aj pre ne. Tu na tom záleží najviac: klient Guzzle predvolene nemá žiadny časový limit. Pri nastavenom request.timeout ho klient bez limitu dostane a dlhší sa naň skráti, vrátane všetkých krokov. Telo nad request.max\_bytes sa oreže a označí — SafeFetch::truncated($response) prečíta aj odpoveď PSR-7. Pre jedno volanie: SafeFetch::policy()->timeout(10)->maxResponseBytes(1\_048\_576), alebo ich zrušíte cez timeout(null) a maxResponseBytes(null).

## Súbežnosť a DNS rebinding

Každý krok sa preloží raz a curl sa pripne presne na posúdené adresy (CURLOPT\_RESOLVE), takže odpoveď DNS, ktorá sa zmení medzi kontrolou a spojením, sa nikdy nevytočí; ďalšia požiadavka sa overí odznova. Súbežné požiadavky jedného klienta (getAsync(), GuzzleHttpPool) zdieľajú jeden curl multi handle ako členovia Http::pool(): každý krok nesie vlastné pripnutie, nové spojenie a žiadne opätovné použitie a dve súbežné požiadavky na rovnaký hostiteľ a port s rôznymi overenými adresami sa odmietnu, nie zmiešajú.

## Testovanie

Http::fake() odpovedá na požiadavky odoslané cez obe metódy a zaznamenáva ich ako pri Http::safe(): platí Http::assertSent(), preventStrayRequests() aj stuby. Pod SafeFetch::fake() sa zaznamená každý krok (assertVetted()) a požiadavka, na ktorú neodpovedá žiadny stub Http::fake(), sa odmietne ešte pred vytočením.

## Čo nie je zaručené

- Zásobník je len taký bezpečný ako jeho handler. Kód, ktorý naň zavolá setHandler() alebo ochranu odstráni cez remove(), ju vyradí z cesty; na Guzzle 7 nahradí celý zásobník aj voľba handler pri požiadavke (Guzzle 8 túto voľbu sám odmietne). Zásobník odovzdajte len kódu, ktorý ho použije ako handler.
- stream => true nestreamuje: handler ochrany je curl, ktorý najprv stiahne celé telo (odpoveď server-sent events príde, až keď ju server ukončí). Obmedzte ju cez request.max\_bytes alebo pravidlá.
- Udalosť ResponseReceived z Laravelu sa pre tieto požiadavky nespustí; RequestSending áno.

## laravel/mcp — podtrieda transportu

Overené na laravel/mcp 1.1.2 a laravel/ai 1.3.0 (Guzzle 8.3); po ich aktualizácii to overte znova. Ani jeden si nezostavuje vlastného klienta Guzzle — oba posielajú cez fasádu Http z Laravelu vo vlastných triedach. HttpTransport z laravel/mcp posiela každú správu JSON-RPC zo send() a reláciu ukončuje v terminateSession(), vždy cez Http::withHeaders(…). Podeďte ho a tieto dve požiadavky zostavte cez SafeFetch::http(); všetko ostatné je protected a použije sa bez zmeny:

```php
final class GuardedMcpTransport extends HttpTransport
{
    // send() and terminateSession(): HttpTransport's own bodies, with
    // Http::withHeaders(...) replaced by
    // SafeFetch::http($this->policy)->withHeaders(...).
}

$client = new WebClient(new GuardedMcpTransport($tenantMcpUrl));
$tools = $client->connect()->tools();

// A named client: registered through laravel/mcp's own factory hook, so Mcp::client('partner')
// and a queued or cached copy of it are rebuilt with the guarded transport.
Mcp::registerClient('partner', fn () => new WebClient(new GuardedMcpTransport($partnerUrl)));
```

- Telá metód skopírujte z verzie laravel/mcp, ktorú používate, a pri aktualizácii ich skopírujte znova.
- Klienti definovaní v config/mcp.php používajú obyčajný transport — zaregistrujte ich namiesto toho cez Mcp::registerClient().
- Klient serializovaný bez mena sa znova zostaví s obyčajným transportom; pomenovaný cez factory z Mcp::registerClient().
- Objavovanie OAuth si adresy pripína samo a sleduje presmerovania Guzzle s kontrolou každého kroku; vnútri ochrany bežať nemôže, lebo tá presmerovania Guzzle odmieta.

## laravel/ai — vzdialené súbory načítajte sami

- Požiadavky na poskytovateľov nemajú háčik pre jednotlivého poskytovateľa a ochrana nemôže byť celoaplikačný Http::globalMiddleware() (potrebuje vlastný handler a odmietala by presmerovania pri každej požiadavke v aplikácii). Ak môže tenant nastaviť základnú URL (OpenAI-kompatibilnú alebo Ollama), posúďte ju pri ukladaní — SafeFetch::vet($url) alebo pravidlo safe\_url — a odchádzajúcu komunikáciu obmedzte aj na okraji siete; táto kontrola sa pri odoslaní nepripína.
- Vzdialené súbory (Image::fromUrl(), Document::fromUrl(), Audio::fromUrl()) idú cez vlastnú ochranu laravel/ai, ktorú za túto vymeniť nemožno. Ak chcete uplatniť svoje pravidlá — zoznam povolených, blokované rozsahy, tabuľku cloudových metadát — súbor načítajte sami a odovzdajte bajty (nižšie). Gateway, ktorá poskytovateľovi pošle priamo URL, na vašom serveri nič nenačíta.
- Bedrock zostavuje klienta AWS SDK s vlastným handlerom; háčik neexistuje a jeho koncové body patria AWS.

```php
$fetched = SafeFetch::fetch($url, maxBytes: 10_000_000, accept: 'image/*');

$image = Image::fromBase64(base64_encode($fetched->body), $fetched->contentType);
```

## Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

[Ďalšie spôsoby podpory vrátane kryptomien](https://roundly-consulting.com/sk/podporte-nas.md)

Odoslaním daru súhlasíte s našimi [podmienkami prijímania darov](https://roundly-consulting.com/sk/podmienky-darov.md).

[Podporte našu open-source prácu (otvorí sa v novej karte)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Pridajte sa k nám na Patreone (otvorí sa v novej karte)](https://www.patreon.com/cw/roundly)

## Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.

[Ponuka do 48 hodín](https://roundly-consulting.com/sk/kontakt.md) [Prezrieť všetky balíky](https://roundly-consulting.com/sk/open-source/navody/safe-fetch-for-laravel.md)
