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