Laravel HTTP client was introduced starting from version 10 of the framework, and then also made available in all previous versions.
It stands out as a powerful tool for making HTTP requests and handling responses from external services. This article will delve into the technical foundations of the Laravel HTTP client, its motivations, and how it simplifies communication with external systems. I’ll also provide code examples to illustrate its usage.
For more technical articles you can follow me on Linkedin or X.
Technical Foundations
The Laravel HTTP client is built on top of the Guzzle HTTP client, which is a widely-used PHP HTTP client that simplifies the process of sending HTTP requests and handling responses in an object oriented way.
Guzzle is great, but it was built as a low level library to model communication with external services. It is widely used to create SDKs to interact with external APIs.
By leveraging Guzzle, Laravel provides a more intuitive and developer-friendly interface while inheriting Guzzle’s robustness and performance.
Guzzle's key features include:
- Synchronous and asynchronous requests
- Support for PSR-7 HTTP message interfaces
- Middleware for modifying requests and responses
- Extensive event-driven architecture
- Efficient connection management and pooling
Laravel wraps these capabilities in a more expressive and “Laravel-esque” syntax, making it easier for developers to perform common tasks and integrate with the rest of the Laravel ecosystem.
Motivation Behind Laravel HTTP Client
Laravel maintainers built the HTTP client to address several common pain points faced by developers when interacting with external services:
Consistency and Ease of Use
By providing a consistent API that adheres to Laravel's conventions, developers can quickly become productive without needing to learn the intricacies of Guzzle.
Integration with Laravel Features
The HTTP client integrates seamlessly with Laravel's features like dependency injection, service containers, events, and testing utilities.
Error Handling and Testing
Laravel's HTTP client includes built-in mechanisms for error handling and simplifies the process of writing tests for HTTP interactions.
Simplifying Communication with External Systems
To get started with the Laravel HTTP client, you can use the Http facade. Here is a simple example of making a GET request:
use Illuminate\Support\Facades\Http;
$response = Http::get('https://api.example.com/users');
if ($response->successful()) {
$users = $response->json();
// Process the users data
} else {
// Handle the error
Log::error('Request failed: ' . $response->body());
}
Sending Data
You can send data using various HTTP methods like POST, PUT, and DELETE. Here’s an example of sending a POST request with JSON data:
$response = Http::post('https://api.example.com/users', [
'name' => 'John Doe',
'email' => 'john@example.com'
]);
if ($response->successful()) {
$user = $response->json();
// Process the user data
} else {
// Handle the error
Log::error('Request failed: ' . $response->body());
}
Handling Responses
The Laravel HTTP client provides several methods to handle responses effectively:
-
successful()
: Checks if the response status code is 200-299. -
clientError()
: Checks if the response status code is 400-499. -
serverError()
: Checks if the response status code is 500-599. -
json()
: Parses the response body as JSON.
Here's an example of handling different response scenarios:
$response = Http::get('https://api.example.com/users/1');
if ($response->successful()) {
$user = $response->json();
// Process the user data
} elseif ($response->clientError()) {
Log::warning('Client error: ' . $response->body());
} elseif ($response->serverError()) {
Log::error('Server error: ' . $response->body());
} else {
Log::error('Unexpected error: ' . $response->body());
}
Headers and Authentication
You can easily set headers and handle authentication. Here's an example using a Bearer token to authenticate on external APIs:
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . $token,
])->get('https://api.example.com/protected-resource');
if ($response->successful()) {
$data = $response->json();
// Process the data
} else {
// Handle the error
Log::error('Request failed: ' . $response->body());
}
Timeout and Retry
Laravel's HTTP client allows setting timeouts and retry mechanisms to handle transient failures. This feature is based on the retry helper function that you may already know:
$response = Http::timeout(10)
->retry(3, 100)
->get('https://api.example.com/resource');
if ($response->successful()) {
$data = $response->json();
// Process the data
} else {
// Handle the error
Log::error('Request failed: ' . $response->body());
}
Macroable
To create custom predefined configurations you can create a macro on the Http client that will store your settings. You can define your macros in the boot method of the AppServiceProvider
:
use Illuminate\Support\Facades\Http;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Http::macro('inspector', function () {
return Http::withHeaders([
'Authorization' => 'Bearer ' . $inspectorToken,
])->baseUrl('https://app.inspector.dev/api');
});
}
You can use the name of the macro to quickly reuse it everywhere in your application:
$response = Http::inspector()->get('/apps');
HTTP Request Middleware
You can use middleware to modify requests and responses. Here's an example of adding a custom header to every request:
Http::macro('withCustomHeader', function () {
return $this->withHeaders([
'X-Custom-Header' => 'CustomValue'
]);
});
// Usage
$response = Http::withCustomHeader()->get('https://api.example.com/resource');
if ($response->successful()) {
$data = $response->json();
// Process the data
} else {
// Handle the error
Log::error('Request failed: ' . $response->body());
}
Testing HTTP Requests
Laravel provides utilities to mock HTTP requests and responses, making it easier to write tests:
use Illuminate\Support\Facades\Http;
Http::fake([
'https://api.example.com/*' => Http::response(['name' => 'John Doe'], 200)
]);
$response = Http::get('https://api.example.com/users/1');
$this->assertTrue($response->successful());
$this->assertEquals('John Doe', $response->json('name'));
Monitor Laravel Http Client activities
Monitoring Laravel HTTP client activities becomes crucial to understanding the impact of communication with external systems on the reliability of your application.
How long do calls to external endpoints take? How many times do they go wrong?
You can use tools like Inspector to visualize each HTTP request performed by your application into the execution timeline.
Learn more in the article below:
https://inspector.dev/laravel-real-time-performance-monitoring-using-inspector-part-1/
For more technical articles you can follow me on Linkedin or X.
Monitor your Laravel application for free
Inspector is a Code Execution Monitoring tool specifically designed for software developers. You don't need to install anything at the server level, just install the Laravel package and you are ready to go.
If you are looking for HTTP monitoring, database query insights, and the ability to forward alerts and notifications into your preferred messaging environment, try Inspector for free. Register your account.
Or learn more on the website: https://inspector.dev