Introductie
De HTTP Client van Laravel (gebouwd op Guzzle) biedt een vloeiende interface voor het maken van HTTP-requests naar externe API's. Correct gebruik betekent het instellen van expliciete timeouts, het implementeren van retry met backoff, het correct afhandelen van fouten, het gebruik van request pooling voor gelijktijdige calls en het faken van requests in tests.
Waarom
- Snel falen: Expliciete timeouts voorkomen dat requests 30+ seconden blijven hangen op API's die niet reageren
- Weerbaarheid: Retry met exponentiële backoff vangt tijdelijke fouten netjes op zonder externe services te overbelasten
- Correctheid: De HTTP Client gooit standaard geen exception bij 4xx/5xx, fouten moeten expliciet worden afgehandeld om te voorkomen dat foutresponsbodies stilzwijgend als data worden gebruikt
- Prestaties:
Http::pool()voert onafhankelijke requests gelijktijdig uit, waardoor sequentiële wachttijden verdwijnen - Betrouwbaarheid van tests:
Http::fake()metpreventStrayRequests()zorgt ervoor dat tests nooit echte API's raken en vangt niet-gemockte calls op
Geschikt voor
- Elke applicatie die communiceert met externe API's
- Services die integreren met betaalproviders, e-mailservices of externe databronnen
- Applicaties waar betrouwbaarheid en prestaties van API's van belang zijn
Minder geschikt voor
- Interne service-naar-service communicatie waarvoor een dedicated client library wordt aangeboden
- Eenvoudige bestandsdownloads of eenmalige scripts waar robuustheid niet cruciaal is
Voorbeelden
Stel altijd expliciete timeouts in
// Slecht: standaard timeout van 30 seconden
$response = Http::get('https://api.example.com/users');
// Goed: expliciete timeouts
$response = Http::timeout(5)
->connectTimeout(3)
->get('https://api.example.com/users');
Definieer voor service-specifieke clients de timeouts in een macro:
Http::macro('github', function () {
return Http::baseUrl('https://api.github.com')
->timeout(10)
->connectTimeout(3)
->withToken(config('services.github.token'));
});
$response = Http::github()->get('/repos/laravel/framework');
Gebruik retry met backoff voor externe API's
// Slecht: geen retry bij tijdelijke fout
$response = Http::post('https://api.stripe.com/v1/charges', $data);
// Goed: exponentiële backoff
$response = Http::retry([100, 500, 1000])
->timeout(10)
->post('https://api.stripe.com/v1/charges', $data);
Handel fouten expliciet af
// Slecht: zou een foutresponsbody als data kunnen gebruiken
$response = Http::get('https://api.example.com/users/1');
$user = $response->json();
// Goed: gooi een exception bij falen
$response = Http::timeout(5)
->get('https://api.example.com/users/1')
->throw();
$user = $response->json();
// Goed: gracieuze degradatie
$response = Http::get('https://api.example.com/users/1');
if ($response->successful()) {
return $response->json();
}
if ($response->notFound()) {
return null;
}
$response->throw();
Gebruik request pooling voor gelijktijdige requests
// Slecht: sequentiële requests
$users = Http::get('https://api.example.com/users')->json();
$posts = Http::get('https://api.example.com/posts')->json();
// Goed: gelijktijdige requests
use Illuminate\Http\Client\Pool;
$responses = Http::pool(fn (Pool $pool) => [
$pool->as('users')->get('https://api.example.com/users'),
$pool->as('posts')->get('https://api.example.com/posts'),
]);
$users = $responses['users']->json();
$posts = $responses['posts']->json();
Fake HTTP-calls in tests
it('syncs user from API', function () {
Http::preventStrayRequests();
Http::fake([
'api.example.com/users/1' => Http::response([
'name' => 'John Doe',
'email' => '[email protected]',
]),
]);
$service = new UserSyncService;
$service->sync(1);
Http::assertSent(function (Request $request) {
return $request->url() === 'https://api.example.com/users/1';
});
});