Laravel Http Client Overview and Monitoring

Valerio Barbera

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.

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:

  1. 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.
  2. Integration with Laravel Features: The HTTP client integrates seamlessly with Laravel’s features like dependency injection, service containers, events, and testing utilities.
  3. 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

Basic Usage

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' => '[email protected]'
]);
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');

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: 

Autofix your Laravel application for free

Inspector is a Code Execution Monitoring tool specifically designed for software developers. You don’t need to install anything on the infrastructure, just install the Laravel package and you are ready to go.

If you are looking for effective automation, and the ability to automatically receive code change proposals to fix application errors try Inspector for free. Register your account.

Or learn more on the website: https://inspector.dev

Related Posts

Laravel Form Request and Data Validation Tutorial

In this article I will talk about Laravel Form Request to send data from your application frontend to the backend. In web applications, data is usually sent via HTML forms: the data entered by the user into the browser is sent to the server and stored in the database eventually. Laravel makes it extremely simple

Upload File in Laravel

You can upload file in Laravel using its beautiful unified API to interact with many different types of storage systems, from local disk to remote object storage like S3. As many other Laravel components you can interact with the application filesystem through the Storage Facade: Illuminate/Support/Facades/Storage This class allows you to access storage drivers called

Laravel Mailable Tutorial

Sending emails in Laravel requires the collaboration between three components: Laravel mailer, Laravel mailable classes, and the Mail facade. Each of the three deals with a different aspect of the lifecycle of sending an email.  Mailers are the drivers to connect email sending services (like AWS SES, Sendgrid, Mailgun, etc.) that the application can use