<?php
use Illuminate\Support\Facades\Http;
// Retry with exponential backoff
$response = Http::retry(3, 100, function ($exception, $request) {
return $exception instanceof ConnectionException;
})->get('https://api.example.com/data');
// Timeout
$response = Http::timeout(5)->get('https://slow-api.com');
// Base URL
$client = Http::baseUrl('https://api.example.com');
$users = $client->get('/users')->json();
$posts = $client->get('/posts')->json();
// Concurrent requests
$responses = Http::pool(fn ($pool) => [
$pool->get('https://api.example.com/users'),
$pool->get('https://api.example.com/posts'),
$pool->get('https://api.example.com/comments'),
]);
[$usersResponse, $postsResponse, $commentsResponse] = $responses;
// Middleware
$response = Http::withMiddleware(
Middleware::mapRequest(function ($request) {
$request->withHeader('X-Request-ID', Str::uuid());
return $request;
})
)->get('https://api.example.com');
<?php
use Illuminate\Support\Facades\Http;
// Simple GET request
$response = Http::get('https://api.example.com/users');
$users = $response->json();
// POST with JSON body
$response = Http::post('https://api.example.com/users', [
'name' => 'Carlos',
'email' => 'carlos@example.com',
]);
// With headers and bearer token
$response = Http::withHeaders([
'Accept' => 'application/json',
'X-Custom-Header' => 'value',
])->withToken($token)->get('https://api.example.com/posts');
// Form data
$response = Http::asForm()->post('https://example.com/login', [
'username' => 'carlos',
'password' => 'secret',
]);
// Multipart (file upload)
$response = Http::attach(
'avatar', file_get_contents('photo.jpg'), 'photo.jpg'
)->post('https://example.com/upload');
// Check response
if ($response->successful()) {
$data = $response->json();
}
if ($response->failed()) {
$error = $response->body();
}
// Throw exception on error
$response = Http::get('...')->throw();
<?php
use Illuminate\Support\Facades\Http;
// Fake all requests
Http::fake();
// Fake specific URLs
Http::fake([
'api.example.com/*' => Http::response(['data' => 'fake'], 200),
'github.com/*' => Http::response(['error' => 'Not found'], 404),
'*' => Http::response(['default' => 'response'], 200),
]);
// Fake with callback
Http::fake(function ($request) {
return Http::response([
'url' => $request->url(),
'method' => $request->method(),
], 200);
});
// Fake sequences
Http::fake([
'api.example.com/*' => Http::sequence()
->push(['data' => 'first'], 200)
->push(['data' => 'second'], 200)
->pushStatus(404),
]);
// Assert requests made
Http::assertSent(function ($request) {
return $request->url() === 'https://api.example.com/users' &&
$request->hasHeader('Authorization');
});
Http::assertSentCount(3);
Http::assertNotSent(fn ($request) => $request->method() === 'DELETE');
Laravel's HTTP client wraps Guzzle with a fluent, expressive API for consuming external APIs. The Http facade provides methods like get(), post(), put(), and delete(). I chain withHeaders(), withToken(), and withBasicAuth() for authentication. The retry() method handles transient failures with exponential backoff. Responses provide json(), body(), status(), and successful() methods. Concurrent requests use pool() for parallel execution. The fake() method mocks responses in tests. Middleware transforms requests globally. Timeout configuration prevents hanging requests. This abstraction makes API integration clean and testable without raw Guzzle complexity.