17

Is it possible to set the option to retry on timeouts in PHP cURL?

I know I can do this by coding it to retry on failure, just wondering if there's some way to do it through an option.

Ben G
  • 26,091
  • 34
  • 103
  • 170

3 Answers3

29

you can use the errno to retry like this:

$curl = curl_init();
curl_setopt_array($curl, $options);
$response = curl_exec($curl);
$retry = 0;
while(curl_errno($curl) == 28 && $retry < 3){
    $response = curl_exec($curl);
    $retry++;
}

$error_codes=array(
    [1] => 'CURLE_UNSUPPORTED_PROTOCOL', 
    [2] => 'CURLE_FAILED_INIT', 
    [3] => 'CURLE_URL_MALFORMAT', 
    [4] => 'CURLE_URL_MALFORMAT_USER', 
    [5] => 'CURLE_COULDNT_RESOLVE_PROXY', 
    [6] => 'CURLE_COULDNT_RESOLVE_HOST', 
    [7] => 'CURLE_COULDNT_CONNECT', 
    [8] => 'CURLE_FTP_WEIRD_SERVER_REPLY',
    [9] => 'CURLE_REMOTE_ACCESS_DENIED',
    [11] => 'CURLE_FTP_WEIRD_PASS_REPLY',
    [13] => 'CURLE_FTP_WEIRD_PASV_REPLY',
    [14]=>'CURLE_FTP_WEIRD_227_FORMAT',
    [15] => 'CURLE_FTP_CANT_GET_HOST',
    [17] => 'CURLE_FTP_COULDNT_SET_TYPE',
    [18] => 'CURLE_PARTIAL_FILE',
    [19] => 'CURLE_FTP_COULDNT_RETR_FILE',
    [21] => 'CURLE_QUOTE_ERROR',
    [22] => 'CURLE_HTTP_RETURNED_ERROR',
    [23] => 'CURLE_WRITE_ERROR',
    [25] => 'CURLE_UPLOAD_FAILED',
    [26] => 'CURLE_READ_ERROR',
    [27] => 'CURLE_OUT_OF_MEMORY',
    [28] => 'CURLE_OPERATION_TIMEDOUT',
    ....
Cyrec
  • 445
  • 4
  • 5
6

Not with the current options available to the PHP cURL extension. On the command line I believe there is the --retry option, but that is not exposed to PHP.

Femi
  • 64,273
  • 8
  • 118
  • 148
0

I was trying to make my file download function be resumable, here's what i've come up with. using fstat() to get what was downloaded and feed that value to curl on failure using the CURLOPT_RESUME_FROM option.

function download_file(string $url): ?string
{
    $name = tempnam(sys_get_temp_dir(), time() . ".tmp");
    $out = fopen($name, 'a+');
    start_over:
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTPHEADER, Utils::make_curl_headers());
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, 0);

        // TODO: SSL
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

        curl_setopt($ch, CURLOPT_FILE, $out);
        curl_setopt($ch, CURLOPT_RESUME_FROM, fstat($out)['size']);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_MAXREDIRS, 5);

        curl_setopt($ch, CURLOPT_NOPROGRESS, false);

        curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, $delayed_progress);
        curl_setopt($ch, CURLOPT_BUFFERSIZE, bytes("64kb"));
        curl_exec($ch);
        curl_close($ch);

        if (curl_errno($ch) !== 0) {
            fwrite(STDOUT, "  ERROR: " . (curl_error($ch) ?? "CONNECTION_ERROR") 
              . ", will try again in 10 seconds..." . PHP_EOL);
            sleep(10);
            goto start_over;
        }
    }
    return $name;
}
Eboubaker
  • 618
  • 7
  • 15