Open In App

How to make asynchronous HTTP requests in PHP ?

Last Updated : 30 Sep, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Asynchronous HTTP requests in PHP allow multiple requests to be sent without waiting for a response before proceeding. This enables non-blocking operations, improving performance by executing other tasks while waiting for the server’s response, typically achieved using libraries like cURL or Guzzle.

To make asynchronous HTTP requests in PHP, you can use cURL’s curl_multi_exec() function for handling multiple requests simultaneously, or utilize libraries like Guzzle, which provides built-in support for asynchronous requests using promises and non-blocking I/O.

Guzzle 6: Guzzle is a PHP HTTP client that helps to send HTTP requests. These methods can be used to send asynchronous HTTP requests.

  • RequestAsync,
  • SendAsync,
  • GetAsync,
  • HeadAsync,
  • PutAsync,
  • PostAsync,
  • DeleteAsync,
  • patchAsync

Download Guzzle php package.Can be installed through composer.

php composer.phar require guzzlehttp/guzzle:~6.0

or

composer require guzzlehttp/guzzle:~6.0

Please include the “autoload” file in the script part of the code so that it loads all the classes and methods.

PHP
<?php

require_once(__DIR__ . '/vendor/autoload.php');
$client = new GuzzleHttp\Client();

$promises = [
    $client->getAsync('http://localhost')
            ->then(function ($response)
    { echo '10'; }),
   
    $client->getAsync('http://www.google.com')
            ->then(function ($response)
    { echo '20'; }),
    
    $client->getAsync('http://localhost')
            ->then(function ($response)
    { echo '30'; }),
    
    $client->getAsync('http://localhost')
            ->then(function ($response)
    { echo '40'; }),
    
    $client->getAsync('http://localhost')
            ->then(function ($response)
    { echo '50'; }),
    
    $client->getAsync('http://localhost')
            ->then(function ($response)
    { echo '60'; }),
    
    $client->getAsync('http://localhost')
            ->then(function ($response)
   { echo '70'; }),
];

$results = GuzzleHttp\Promise\unwrap($promises);

// Please wait for a while to complete 
// the requests(some of them may fail)
$results = GuzzleHttp\Promise\settle(
        $promises)->wait();
        
print "finish/over." . PHP_EOL;
?>

In the above code, the “autoload” file is included, and then the Guzzle Http client object is created which is stored in the “client” variable and for each Http request getAsync() method is used with the URL. The request getting the first response will print the number. The order of the request will not matter.

Asynchronous HTTP requests using Promise: A single result of an asynchronous operation represents a Promise. Asynchronous requests are used in the non-blocking of the HTTP operations. When asynchronous HTTP requests send a promise, it gets returned.

Execute a request using HTTPlug:

$request = $messageFactory->createRequest(
'GET', 'http://php-http.org');
$promise = $client->sendAsyncRequest($request);
echo 'Non-blocking!';

Wait: The “promise” which is returned from the above, implements http\Promise\Promise. The response is not known yet during this point of time. Wait for that response to arrive.

try {
$response = $promise->wait();
} catch (\Exception $exception) {
echo $exception->getMessage();
}

Then: Instead of waiting, we can perform steps asynchronously. Call the then method with two arguments.

  1. One callback that will be executed if the request turns out to be successful.
  2. Callback that will be executed if the request results in an error.
  
// Success Callback
function (ResponseInterface $response) {

echo 'New response!';

// Write status code to the log file
file_put_contents('responses.log',
$response->getStatusCode() . "\n", FILE_APPEND);
return $response;
},

// Failure Callback
function (\Exception $exception) {
echo 'We have a problem';
throw $exception;
}

Concurrency in Promise: Concurrency means multiple computations taking place at the same time. It is good when we deal with a lot of request at the same time. For concurrency, we must use “EachPromise” class and yield generator and at last add wait() to the end of the program.

PHP
<?php

use GuzzleHttp\Promise\EachPromise;
use GuzzleHttp\Psr7\Response;
 
$users = ['one', 'two', 'three'];
 
$promises = (function () use ($users) {
    foreach ($users as $user) {
        
        // Using generator
        yield $this->getAsync(
   'https://api.demo.com/v1/users?username='
        . $user);        
    }
})();
 
$eachPromise = new EachPromise($promises, [
    
    // Number of concurrency
    'concurrency' => 4,
    'fulfilled' => function (Response $response) {
        if ($response->getStatusCode() == 200) {
            $user = json_decode(
                $response->getBody(), true);
            
            // processing response of the user
        }
    },
    
    'rejected' => function ($reason) {
    // handle promise rejected 
    }
]);
 
$eachPromise->promise()->wait();
?>

Building a multi-thread cURL request: Generally, we can handle multiple requests. First, we trigger the first one and process the response, then the second and third, and so on. But, this process is slow and time-consuming. But cURL offers the curl_multi_* functions to handle any async requests.

$running = null;
$mh = curl_multi_init();

$ch1 = curl_init();
curl_setopt($ch1, CURLOPT_URL, 'https://endpoint.com');

// Other curl options....
curl_multi_add_handle($mh, $ch1);

$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_URL, 'https://endpoint.com');

// Other curl options....
curl_multi_add_handle($mh, $ch2);

do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running > 0);

$r1 = curl_multi_getcontent($ch1);
$r2 = curl_multi_getcontent($ch2);
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);

The responses get collected in the “r1” and “r2” variables. With the help of these cURL functions, we can trigger requests parallel to save time and process the responses quicker.



Next Article

Similar Reads