Was ist der HTTP-Client?
Der HTTP-Client von Laravel ist eine bequeme API auf Basis von Guzzle .
Über die Facade Http senden Sie kompakt HTTP-Anfragen an externe Webdienste und APIs.
use Illuminate\Support\Facades\ Http ;
$response = Http :: get ( 'https://api.example.com/users' );
Guzzle ist bereits vorinstalliert, sodass Sie ohne zusätzliche Konfiguration sofort loslegen können.
Grundlegende Anfragen
GET-Anfrage
use Illuminate\Support\Facades\ Http ;
$response = Http :: get ( 'https://api.example.com/users' );
Query-Parameter übergeben Sie als Array.
$response = Http :: get ( 'https://api.example.com/users' , [
'page' => 1 ,
'per_page' => 20 ,
]);
POST-Anfrage
Standardmäßig werden Daten als application/json gesendet.
$response = Http :: post ( 'https://api.example.com/users' , [
'name' => 'Yamada Taro' ,
'email' => '[email protected] ' ,
]);
PUT / PATCH / DELETE
// PUT
$response = Http :: put ( 'https://api.example.com/users/1' , [
'name' => 'Yamada Hanako' ,
]);
// PATCH
$response = Http :: patch ( 'https://api.example.com/users/1' , [
'email' => '[email protected] ' ,
]);
// DELETE
$response = Http :: delete ( 'https://api.example.com/users/1' );
Antworten verarbeiten
Methoden wie Http::get() liefern eine Instanz von Illuminate\Http\Client\Response.
Diese bietet viele Möglichkeiten, die Antwort zu inspizieren.
$response = Http :: get ( 'https://api.example.com/users/1' );
// Response-Body
$response -> body (); // Als String
$response -> json (); // Als Array
$response -> json ( 'name' ); // Einzelnen JSON-Schlüssel abrufen
$response -> object (); // Als stdClass-Objekt
$response -> collect (); // Als Collection
// Status
$response -> status (); // Statuscode (z. B. 200)
$response -> successful (); // true bei 2xx
$response -> failed (); // true bei 4xx/5xx
$response -> clientError (); // true bei 4xx
$response -> serverError (); // true bei 5xx
// Prüfmethoden für häufige Statuscodes
$response -> ok (); // 200
$response -> created (); // 201
$response -> noContent (); // 204
$response -> notFound (); // 404
$response -> unauthorized (); // 401
$response -> forbidden (); // 403
$response -> unprocessableEntity (); // 422
$response -> tooManyRequests (); // 429
Auf JSON-Werte können Sie auch per Array-Zugriff zugreifen.
$name = Http :: get ( 'https://api.example.com/users/1' )[ 'name' ];
Anfrage-Optionen
$response = Http :: withHeaders ([
'X-Api-Version' => '2' ,
'Accept-Language' => 'de' ,
]) -> get ( 'https://api.example.com/users' );
Um application/json als akzeptierten Content-Type anzugeben, ist acceptJson() praktisch.
$response = Http :: acceptJson () -> get ( 'https://api.example.com/users' );
Für CSRF-Header (X-CSRF-TOKEN / X-XSRF-TOKEN) bei AJAX-Anfragen aus dem Browser an Laravel-Endpunkte lesen Sie den Abschnitt CSRF-Schutz .
Authentifizierung
Bearer-Token (am gängigsten):
$response = Http :: withToken ( $token ) -> get ( 'https://api.example.com/me' );
Basic Auth :
$response = Http :: withBasicAuth ( '[email protected] ' , 'password' )
-> get ( 'https://api.example.com/private' );
Basis-URL setzen
Wenn Sie viele Anfragen an denselben Host senden, bündeln Sie das mit baseUrl().
$response = Http :: baseUrl ( 'https://api.example.com' )
-> withToken ( $token )
-> get ( '/users/1' );
Um Daten als application/x-www-form-urlencoded zu senden, verwenden Sie asForm().
$response = Http :: asForm () -> post ( 'https://api.example.com/login' , [
'username' => 'taro' ,
'password' => 'secret' ,
]);
Timeouts
// Response-Timeout (Standard: 30 Sekunden)
$response = Http :: timeout ( 10 ) -> get ( 'https://api.example.com/slow-endpoint' );
// Verbindungs-Timeout (Standard: 10 Sekunden)
$response = Http :: connectTimeout ( 5 ) -> get ( 'https://api.example.com/endpoint' );
Wird das Timeout überschritten, wird eine Illuminate\Http\Client\ConnectionException ausgelöst.
Wir empfehlen, bei Aufrufen externer APIs immer ein Timeout zu setzen.
Retries
Für temporäre Netzwerkstörungen oder Serverfehler können Sie automatische Wiederholungen konfigurieren.
// Bis zu 3 Versuche mit 100 ms Abstand
$response = Http :: retry ( 3 , 100 ) -> post ( 'https://api.example.com/orders' , $data );
Bedingte Wiederholung (z. B. nur bei Verbindungsfehlern):
use Illuminate\Http\Client\ PendingRequest ;
use Throwable ;
use Illuminate\Http\Client\ ConnectionException ;
$response = Http :: retry ( 3 , 100 , function ( Throwable $exception , PendingRequest $request ) {
return $exception instanceof ConnectionException ;
}) -> post ( 'https://api.example.com/orders' , $data );
Fehlerbehandlung
Fehler manuell prüfen
Der HTTP-Client wirft standardmäßig keine Ausnahmen für 4xx-/5xx-Antworten.
Nutzen Sie failed() oder clientError(), um solche Zustände abzufragen.
$response = Http :: get ( 'https://api.example.com/users/999' );
if ( $response -> notFound ()) {
// 404 behandeln
}
if ( $response -> failed ()) {
// Fehler protokollieren
logger () -> error ( 'API request failed' , [ 'status' => $response -> status ()]);
}
Ausnahmen auslösen
Mit throw() löst der Client bei Fehlerantworten eine Illuminate\Http\Client\RequestException aus.
// Wirft bei 4xx/5xx eine Ausnahme
$response = Http :: post ( 'https://api.example.com/users' , $data ) -> throw ();
// throwIf(): löst aus, wenn die Bedingung erfüllt ist (eigenständiges Beispiel)
$response = Http :: get ( 'https://api.example.com/users/1' );
$response -> throwIf ( $response -> status () === 422 );
// throwUnlessStatus(): wirft, wenn der Status nicht wie erwartet ist
$response = Http :: post ( 'https://api.example.com/orders' , $data );
$response -> throwUnlessStatus ( 201 );
throw() gibt die Antwort zurück und lässt sich verketten.
$user = Http :: post ( 'https://api.example.com/users' , $data )
-> throw ()
-> json ();
Fehler abfangen und behandeln:
use Illuminate\Http\Client\ RequestException ;
use Illuminate\Http\Client\ ConnectionException ;
try {
$response = Http :: timeout ( 5 )
-> post ( 'https://api.example.com/users' , $data )
-> throw ();
} catch ( ConnectionException $e ) {
// Timeout oder Verbindungsfehler
logger () -> error ( 'Connection failed: ' . $e -> getMessage ());
} catch ( RequestException $e ) {
// 4xx / 5xx
logger () -> error ( 'API error' , [ 'status' => $e -> response -> status ()]);
}
Parallele Anfragen
Um mehrere APIs gleichzeitig anzusprechen, verwenden Sie pool().
use Illuminate\Http\Client\ Pool ;
use Illuminate\Support\Facades\ Http ;
$responses = Http :: pool ( fn ( Pool $pool ) => [
$pool -> as ( 'users' ) -> get ( 'https://api.example.com/users' ),
$pool -> as ( 'posts' ) -> get ( 'https://api.example.com/posts' ),
$pool -> as ( 'comments' ) -> get ( 'https://api.example.com/comments' ),
]);
$users = $responses [ 'users' ] -> json ();
$posts = $responses [ 'posts' ] -> json ();
$comments = $responses [ 'comments' ] -> json ();
Deutlich schneller als sequenzielle Aufrufe. Ideal für Dashboards, die mehrere externe APIs abrufen.
Tests
Mocking mit Http::fake()
In Tests simulieren Sie Antworten mit Http::fake(), ohne echte Anfragen zu senden.
use Illuminate\Support\Facades\ Http ;
Http :: fake ();
// Alle Anfragen liefern 200
$response = Http :: get ( 'https://api.example.com/users' );
$response -> successful (); // true
Antworten pro URL definieren:
Http :: fake ([
'api.example.com/users/*' => Http :: response ([ 'id' => 1 , 'name' => 'Yamada Taro' ], 200 ),
'api.example.com/posts/*' => Http :: response ([ 'error' => 'Not Found' ], 404 ),
'*' => Http :: response ( 'OK' , 200 ), // Alles Übrige
]);
Antwort-Sequenzen (mehrfaches Aufrufen liefert unterschiedliche Antworten):
Http :: fake ([
// 1. Aufruf: 200, 2. Aufruf: 200, 3. Aufruf: 429
// Ist die Sequenz erschöpft, werfen weitere Aufrufe Ausnahmen.
'api.example.com/*' => Http :: sequence ()
-> push ([ 'id' => 1 ], 200 )
-> push ([ 'id' => 2 ], 200 )
-> pushStatus ( 429 ),
]);
Anfragen verifizieren
Mit Http::assertSent() prüfen Sie den Inhalt gesendeter Anfragen.
use Illuminate\Http\Client\ Request ;
use Illuminate\Support\Facades\ Http ;
Http :: fake ();
Http :: withToken ( 'my-token' ) -> post ( 'https://api.example.com/users' , [
'name' => 'Yamada Taro' ,
]);
Http :: assertSent ( function ( Request $request ) {
return $request -> url () === 'https://api.example.com/users'
&& $request -> hasHeader ( 'Authorization' , 'Bearer my-token' )
&& $request [ 'name' ] === 'Yamada Taro' ;
});
// Sicherstellen, dass eine bestimmte Anfrage nicht gesendet wurde
Http :: assertNotSent ( function ( Request $request ) {
return $request -> url () === 'https://api.example.com/admin' ;
});
// Anzahl der gesendeten Anfragen prüfen
Http :: assertSentCount ( 1 );
Rufen Sie in Tests immer zuerst Http::fake() auf.
Andernfalls landen Anfragen tatsächlich beim externen Dienst.
Mit Http::preventStrayRequests() lassen Sie unmodifizierte Aufrufe eine Ausnahme auslösen.
Stray-Anfragen verhindern
Http :: preventStrayRequests ();
Http :: fake ([
'api.example.com/*' => Http :: response ([ 'ok' => true ]),
]);
// Nicht gefakte URLs führen zu einer Ausnahme
Http :: get ( 'https://other.example.com/endpoint' ); // Ausnahme
Praxisbeispiel: Service-Klasse für einen externen API-Aufruf
In der Praxis ist es Best Practice, die Client-Logik in eine Service-Klasse zu kapseln.
Service-Klasse erstellen
<? php
namespace App\Services ;
use Illuminate\Http\Client\ RequestException ;
use Illuminate\Http\Client\ ConnectionException ;
use Illuminate\Support\Facades\ Http ;
class GitHubService
{
private string $baseUrl = 'https://api.github.com' ;
public function __construct (
private readonly string $token ,
) {}
/**
* Benutzerinformationen abrufen.
*
* @throws ConnectionException
* @throws RequestException
*/
public function getUser ( string $username ) : array
{
return Http :: baseUrl ( $this -> baseUrl )
-> withToken ( $this -> token )
-> acceptJson ()
-> timeout ( 10 )
-> get ( "/users/{ $username }" )
-> throw ()
-> json ();
}
/**
* Liste der Repositories abrufen.
*
* @throws ConnectionException
* @throws RequestException
*/
public function getRepositories ( string $username , int $page = 1 ) : array
{
return Http :: baseUrl ( $this -> baseUrl )
-> withToken ( $this -> token )
-> acceptJson ()
-> timeout ( 10 )
-> retry ( 2 , 500 )
-> get ( "/users/{ $username }/repos" , [
'page' => $page ,
'per_page' => 30 ,
'sort' => 'updated' ,
])
-> throw ()
-> json ();
}
}
Im Service Provider registrieren
// app/Providers/AppServiceProvider.php
use App\Services\ GitHubService ;
public function register () : void
{
$this -> app -> singleton ( GitHubService :: class , function () {
return new GitHubService (
token : config ( 'services.github.token' ),
);
});
}
// config/services.php
'github' => [
'token' => env ( 'GITHUB_TOKEN' ),
],
Aus dem Controller nutzen
<? php
namespace App\Http\Controllers ;
use App\Services\ GitHubService ;
use Illuminate\Http\Client\ RequestException ;
use Illuminate\Http\Client\ ConnectionException ;
use Illuminate\Http\ JsonResponse ;
class GitHubController extends Controller
{
public function __construct (
private readonly GitHubService $github ,
) {}
public function show ( string $username ) : JsonResponse
{
try {
$user = $this -> github -> getUser ( $username );
return response () -> json ( $user );
} catch ( ConnectionException ) {
return response () -> json ([ 'error' => 'Verbindung zur GitHub-API fehlgeschlagen.' ], 503 );
} catch ( RequestException $e ) {
$status = $e -> response -> status ();
if ( $status === 404 ) {
return response () -> json ([ 'error' => 'Nutzer nicht gefunden.' ], 404 );
}
return response () -> json ([ 'error' => 'Fehler bei der GitHub-API.' ], 502 );
}
}
}
Tests schreiben
<? php
namespace Tests\Unit\Services ;
use App\Services\ GitHubService ;
use Illuminate\Http\Client\ ConnectionException ;
use Illuminate\Http\Client\ RequestException ;
use Illuminate\Support\Facades\ Http ;
use Tests\ TestCase ;
class GitHubServiceTest extends TestCase
{
private GitHubService $service ;
protected function setUp () : void
{
parent :: setUp ();
Http :: fake ([
'api.github.com/users/octocat' => Http :: response ([
'login' => 'octocat' ,
'name' => 'The Octocat' ,
'public_repos' => 8 ,
], 200 ),
'api.github.com/users/notfound' => Http :: response (
[ 'message' => 'Not Found' ],
404
),
]);
$this -> service = new GitHubService ( token : 'test-token' );
}
public function test_kann_benutzer_abrufen () : void
{
$user = $this -> service -> getUser ( 'octocat' );
$this -> assertEquals ( 'octocat' , $user [ 'login' ]);
$this -> assertEquals ( 'The Octocat' , $user [ 'name' ]);
Http :: assertSent ( function ( $request ) {
return $request -> url () === 'https://api.github.com/users/octocat'
&& $request -> hasHeader ( 'Authorization' , 'Bearer test-token' );
});
}
public function test_nicht_gefundener_benutzer_wirft_ausnahme () : void
{
$this -> expectException ( RequestException :: class );
$this -> service -> getUser ( 'notfound' );
}
}
Zusammenfassung
Methode Verwendung Http::get($url, $query)GET-Anfrage Http::post($url, $data)POST-Anfrage (JSON) Http::put($url, $data)PUT-Anfrage Http::patch($url, $data)PATCH-Anfrage Http::delete($url)DELETE-Anfrage ->withToken($token)Bearer-Auth ->withHeaders($headers)Eigene Header ->timeout($seconds)Timeout festlegen ->retry($times, $sleep)Automatische Wiederholung ->throw()Ausnahme bei Fehler Http::fake()Test-Mocks Http::pool($callback)Parallele Anfragen
Methoden zur Statusprüfung
Methode Beschreibung successful()2xx failed()4xx/5xx clientError()4xx serverError()5xx ok()200 created()201 notFound()404 unauthorized()401 forbidden()403 unprocessableEntity()422 tooManyRequests()429
Best Practices für externe APIs
Kapseln Sie die HTTP-Logik in einer Service-Klasse.
Setzen Sie immer ein Timeout (timeout() und connectTimeout()).
Konfigurieren Sie Wiederholungen für transiente Ausfälle (retry()).
Nutzen Sie in Tests konsequent Http::fake(), um externe APIs nicht wirklich anzusprechen.
Http::preventStrayRequests() im Testsetup schafft zusätzliche Sicherheit.
Legen Sie API-Tokens und Zugangsdaten in Umgebungsvariablen und in config/services.php ab.
Zuletzt geändert am 13. Juli 2026