Laravel Http Client Overview and Monitoring

Valerio - Sep 30 - - Dev Community

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());
}
Enter fullscreen mode Exit fullscreen mode

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());
}
Enter fullscreen mode Exit fullscreen mode

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());
}
Enter fullscreen mode Exit fullscreen mode

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());
}
Enter fullscreen mode Exit fullscreen mode

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());
}
Enter fullscreen mode Exit fullscreen mode

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');
    });
}
Enter fullscreen mode Exit fullscreen mode

You can use the name of the macro to quickly reuse it everywhere in your application:

$response = Http::inspector()->get('/apps');
Enter fullscreen mode Exit fullscreen mode

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());
}
Enter fullscreen mode Exit fullscreen mode

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'));
Enter fullscreen mode Exit fullscreen mode

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

Laravel application monitoring

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .