Повторная попытка cURL в PHP

#php #curl #libcurl

#php #curl #libcurl

Вопрос:

Возможно ли установить опцию повторной попытки по тайм-аутам в PHP cURL?

Я знаю, что могу сделать это, закодировав его для повторной попытки при сбое, просто интересно, есть ли какой-нибудь способ сделать это с помощью опции.

Комментарии:

1. список всех параметров curl

2. лучшим способом было бы повторить попытку при сбое

Ответ №1:

вы можете использовать errno для повторной попытки следующим образом:

 $curl = curl_init();
curl_setopt_array($curl, $options);
$response = curl_exec($curl);
$retry = 0;
while(curl_errno($curl) == 28 amp;amp; $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',
    ....
  

Комментарии:

1. Лучше использовать do {} while (), чтобы избежать дублирования кода (в случае, если тело цикла содержит несколько строк логики)

2. Если проблема не устраняется, также может быть хорошей идеей добавить sleep($delay) в цикл, чтобы увеличить вероятность устранения перегрузки сети между повторными попытками.

Ответ №2:

Не с текущими параметрами, доступными для расширения PHP cURL. Я полагаю, что в командной строке есть --retry опция, но она не доступна для PHP.

Ответ №3:

Я пытался сделать мою функцию загрузки файлов возобновляемой, вот что у меня получилось. используя fstat() , чтобы получить то, что было загружено, и передать это значение в curl при сбое, используя CURLOPT_RESUME_FROM опцию.

 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;
}