Async Curl Request in PHP

Async curl request in PHP

So what you want to do is asynchronous execution of the cUrl Requests.

So you would need a asynchronous/parallel processing library for php.



Async cURL

The other way is to use the built in asynchronous cURL functions.

So, when using curl_multi_*, your code would look something like:

$username = 'xxxxx'; 
$api_onfleet = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$url_onfleet = "https://onfleet.com/api/v2/tasks";

curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
$request = $url.'api/mail.send.json';

// Generate curl request
$session = curl_init($request);
// Tell curl to use HTTP POST
curl_setopt ($session, CURLOPT_POST, true);
// Tell curl that this is the body of the POST
curl_setopt ($session, CURLOPT_POSTFIELDS, $params);
// Tell curl not to return headers, but do return the response
curl_setopt($session, CURLOPT_HEADER, false);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);


// Post the Pickup task to Onfleet
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url_onfleet);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERPWD, $api_onfleet);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_ENCODING, "");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"destination":{"address":{"unparsed":"'.$pickup_address.'"},"notes":"'.$comments.'"},"recipients":[{"name":"'.$name.'","phone":"+61'.$phone.'","notes":"Number of riders: '.$riders.'"}],"completeBefore":'.$timestamp.',"pickupTask":"yes","autoAssign":{"mode":"distance"}}');
$mh = curl_multi_init();
curl_multi_add_handle($mh,$session);
curl_multi_add_handle($mh,$ch);

$active = null;
//execute the handles
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
//close the handles
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);

Suggested Reading:

  1. curl_multi_init()
  2. curl_multi_exec()
  3. curl_multi_add_handle()
  4. curl_multi_remove_handle()


pThreads

One of the prominent threading libraries for php is pthreads

You would need to first get the dll/so file and save it in the php/ext dir, and enable that extension in php.ini.

After That, this code would do your job:

class Request1 extends Thread {
$username = 'xxxxx';
$api_onfleet = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$url_onfleet = "https://onfleet.com/api/v2/tasks";
public function run() {
curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
$request = $this->url.'api/mail.send.json';

// Generate curl request
$session = curl_init($request);
// Tell curl to use HTTP POST
curl_setopt ($session, CURLOPT_POST, true);
// Tell curl that this is the body of the POST
curl_setopt ($session, CURLOPT_POSTFIELDS, $params);
// Tell curl not to return headers, but do return the response
curl_setopt($session, CURLOPT_HEADER, false);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);

// obtain response
$response = curl_exec($session);
curl_close($session);
}
}


class Request2 extends Thread {
$username = 'xxxxx';
$api_onfleet = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$url_onfleet = "https://onfleet.com/api/v2/tasks";
public function run() {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url_onfleet);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERPWD, $this->api_onfleet);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_ENCODING, "");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, '{"destination":{"address":{"unparsed":"'.$pickup_address.'"},"notes":"'.$comments.'"},"recipients":[{"name":"'.$name.'","phone":"+61'.$phone.'","notes":"Number of riders: '.$riders.'"}],"completeBefore":'.$timestamp.',"pickupTask":"yes","autoAssign":{"mode":"distance"}}');

$result_pickup = curl_exec($ch);
curl_close($ch);

// Post the Dropoff task to Onfleet
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $this->url_onfleet);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_USERPWD, $this->api_onfleet);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_ENCODING, "");
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, '{"destination":{"address":{"unparsed":"'.$dropoff_address.'"},"notes":"'.$comments.'"},"recipients":[{"name":"'.$name.'","phone":"+61'.$phone.'","notes":"Number of riders: '.$riders.'"}],"autoAssign":{"mode":"distance"}}');

$result_dropoff = curl_exec($curl);
curl_close($curl);
}
}

$req1 = new Request1();
$req1->start();
$req2 = new Request2();
$req2->start();

So, basically you need to create a class which extends the Thread class and everything you want to run asynchronously (rather parallely), would be put in the function run() of the class.

When you want to start the thread just instantiate the class in a variable, and call the start method of the object, like $threadsObject->start() and everything in the run() would be executed on another thread.

Reference:

  1. class::Thread
  2. Thread::start

That's it.

Is making asynchronous HTTP requests possible with PHP?

Yes.

There is the multirequest PHP library (or see: archived Google Code project). It's a multi-threaded CURL library.

As another solution, you could write a script that does that in a language that supports threading, like Ruby or Python. Then, just call the script with PHP. Seems rather simple.

This is ASYNC REQUEST. Can you help me change to Curl in php?

You can try below code :

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://api.offertest.net/offertest?async=true');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"userid\":\"oeAuUNreRW6cypwJpcgnlQ\", \"country\":\"us\", \"url\":\"http://www.google.com/\",\"platform\": \"android\", \"callback\":\"http://{YOURAPIURL}/offertest/{YOURCAMPAIGNID}/result\"}");
curl_setopt($ch, CURLOPT_POST, 1);

$headers = array();
$headers[] = 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJvZUF1VU5yZVJXNmN5cHdKcGNnbmxRIiwiaWF0IjoxNTUxOTMxNzU3LCJqdGkiOiJUanNUaF9sUkY4MUR0VER5aWQ3bG9BIn0.DLgPiNNDHJMZTufUHS5nYTD_j3ImvxIfhMNrqlcl4LA';
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close ($ch);

PHP waiting for curl to finish before returning

The reason this does not work is, that PHP curl calls are always synchronous and your timeout is set to 30 seconds, which far exceeds the max. 3 seconds that is allowed for Slash commands.

But there is a fix to make this work. You just need these small changes:

  1. Set the curl timeout to a smaller value to ensure your first script is completing below the 3 second threshold, e.g. set CURLOPT_TIMEOUT_MS to 400, which defines a timeout of 400 ms.

  2. Set CURLOPT_NOSIGNAL to 1 in your first script. This is required for the timeout to work in UNIX based systems.

  3. Make sure to ignore timeout-errors (CURL ERROR 28) in your first script, since your curl should always return a timeout error.

  4. Make sure your second script is not aborted by the forced timeout by adding this line: ignore_user_abort(true);

See also this answer for a full example.

P.S.: You to not need any buffer flushing for this approach.

Asynchronous cURL using POST

You'll need to create a new curl handle for every request, and then register it with http://www.php.net/manual/en/function.curl-multi-add-handle.php

here is some code i ripped out and adapted from my code base, have in mind that you should add error checking in there.

function CreateHandle($url , $data) {
$curlHandle = curl_init($url);

$defaultOptions = array (
CURLOPT_COOKIEJAR => 'cookies.txt' ,
CURLOPT_COOKIEFILE => 'cookies.txt' ,

CURLOPT_ENCODING => "gzip" ,
CURLOPT_FOLLOWLOCATION => true ,
CURLOPT_RETURNTRANSFER => true ,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $data
);

curl_setopt_array($curlHandle , $defaultOptions);

return $curlHandle;
}

function MultiRequests($urls , $data) {
$curlMultiHandle = curl_multi_init();

$curlHandles = array();
$responses = array();

foreach($urls as $id => $url) {
$curlHandles[$id] = CreateHandle($url , $data[$id]);
curl_multi_add_handle($curlMultiHandle, $curlHandles[$id]);
}

$running = null;
do {
curl_multi_exec($curlMultiHandle, $running);
} while($running > 0);

foreach($curlHandles as $id => $handle) {
$responses[$id] = curl_multi_getcontent($handle);
curl_multi_remove_handle($curlMultiHandle, $handle);
}
curl_multi_close($curlMultiHandle);

return $responses;
}


Related Topics



Leave a reply



Submit