Asynchronous cURL Requests

A possibly underused technique available to PHP developers is the ability to spawn a background PHP script without JavaScript. All you need to do this is the cURL library and a few lines of code. Let me explain, suppose you have a script that is going to take minutes (or longer) to run, you don’t want to sit looking at a blank screen, and your users certainly won’t! In this kind of scenario you can separate out that logic to a background file and leave your view free for other things, perhaps to query the database to see how the background process is doing?

All you need to do to set this off is use the following code (entering your own url):

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'http://www.yoursite.com/background-script.php');
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);

curl_exec($ch);
curl_close($ch);

There is an irritating 1 second delay for this to finish, but this cannot be helped (so far as I am aware!)

Remember to be careful with this technique (especially if you turn off script timeout etc) and build in a control to stop the script should you need to (database query every minute? or a lock file?)

Enjoy!

Update

It has been pointed out to me that on modern systems (cURL 7.16.2 or higher and PHP 5.2.3 or above) you can use a millisecond option to reduce the delay effectively to zero.

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'http://www.yoursite.com/background-script.php');
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1);

curl_exec($ch);
curl_close($ch);

9 Responses to Asynchronous cURL Requests

  1. Mercure says:

    You can use CURLOPT_TIMEOUT_MS instead of CURLOPT_TIMEOUT to reduce the delay.

  2. Paul Norman says:

    @Mercure That is true if you have cUrl 7.16.2 or higher and PHP 5.2.3 or up.

  3. Andrew says:

    Have you ever looked into receiving notifications from the script as it completes parts so you could have a status page letting the user know where the script’s at and how much longer they have to wait?

  4. Paul Norman says:

    You can’t return anything using this method (the script has moved on), but you can use the daemon processes to update a database with their status. You can then use your main process (the user’s process) to update their status page periodically (i.e. query the database) using header refreshes or JavaScript to keep the information up to date.

    If you are after tracking uploads or something like that then the APC library is the answer. This probably holds some other nifty uses too, though I haven’t explored any…

  5. LM PHP-Werbeagentur says:

    Here is a fsockopen-version. I got the gut feeling that it’s the best performing one – IF you’ve already some configvars and don’t need to fill $host via preg_match().

    $fp = fsockopen($host, 80);
    if($fp !== false)
    {
      $out  = "GET $path HTTP/1.1\r\n";
      $out .= "Host: $host\r\n";
      $out .= "Connection: Close\r\n\r\n";
     
      fwrite($fp, $out);
      fclose($fp);
    }
  6. Brad says:

    Wouldn’t a better option to be to use exec and call the php file directly? With this technique, you’re incurring a lot of extra overhead as well as opening up a “background” script to the abuse of the internet at large.

  7. Paul Norman says:

    @Brad, you can use exec assuming you have the correct system permissions (and a framework / script that is CLI happy) and append something like “> /dev/null 2>/dev/null &” to your exec call to make it asynchronous (re-routes stdio and stderr to null values and makes the process ‘background’). As to the overhead? I’m not sure what you mean, but I’d imagine in real terms any resource / speed difference is minimal. cURL also makes it trivial to pass GET / POST variables to the script for security / to stop external users triggering the script. If you are using a shared server I’d say giving +x permissions to a script available to the standard web user poses a greater potential for abuse…

    There’s another nice exec example here: http://stackoverflow.com/questions/45953/php-execute-a-background-process#45966

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>