Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Fire and Forget POST Request

I'm trying to create a fire and forget method in PHP so that I can POST data to a web server and not have wait for a response. I read that this could be achieved by using CURL like in the following code:

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
curl_exec($ch);
curl_close($ch);

However I don't think it works as I expect. For example if the URL I send the request to has an error it causes my script to throw an error as well. If it was fire and forget I would expect that not to happen.

Can anyone tell me whether I'm doing something wrong or offer an alternative suggestion. I'm using Windows locally and Linux for dev, staging and production environments.

UPDATE

I have found an alternative solution here: http://blog.markturansky.com/archives/205

I've cleaned it up into the code below:

function curl_post_async($url, $params = array())
{
    // create POST string   
    $post_params = array();
    foreach ($params as $key => &$val) 
    {
        $post_params[] = $key . '=' . urlencode($val);
    }
    $post_string = implode('&', $post_params);

    // get URL segments
    $parts = parse_url($url);

    // workout port and open socket
    $port = isset($parts['port']) ? $parts['port'] : 80;
    $fp = fsockopen($parts['host'], $port, $errno, $errstr, 30);

    // create output string
    $output  = "POST " . $parts['path'] . " HTTP/1.1\r\n";
    $output .= "Host: " . $parts['host'] . "\r\n";
    $output .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $output .= "Content-Length: " . strlen($post_string) . "\r\n";
    $output .= "Connection: Close\r\n\r\n";
    $output .= isset($post_string) ? $post_string : '';

    // send output to $url handle
    fwrite($fp, $output);
    fclose($fp);
}

This one seems to work better for me.

Is it a valid solution?

like image 930
diggersworld Avatar asked Jan 29 '13 16:01

diggersworld


1 Answers

Yes, using sockets is the way to go if you don't care about the response from the URL you're calling. This is because socket connection can be terminated straight after sending the request without waiting and this is exactly what you're after - Fire and Forget.

Two notes though:

  1. It's no longer a cURL request, so it's worth renaming the function. :)
  2. It's definitely worth checking whether the socket could've been opened to prevent the script from complaining later when if fails:

    $fp = fsockopen($parts['host'], $port, $errno, $errstr, 30);
    
    if ( ! $fp)
    {
       return FALSE;
    }
    

It's worth linking to the original source of the fsocket() script you're now using:
http://w-shadow.com/blog/2007/10/16/how-to-run-a-php-script-in-the-background/

like image 61
Michal M Avatar answered Oct 06 '22 04:10

Michal M