PHP 8.4: Curl: Новая опция CURLOPT_PREREQFUNCTION
CURLOPT_PREREQFUNCTION, позволяющую задать пользовательский callable для принятия решения о продолжении или прерывании запроса. Эта возможность доступна, если расширение собрано с libcurl 7.80.0 или более поздней версии.Обратный вызов CURLOPT_PREREQFUNCTION вызывается после установления начального соединения и перед отправкой запроса. Например, при запросе HTTPS обратный вызов CURLOPT_PREREQFUNCTION вызывается после установления HTTPS-соединения (DNS + TCP + TLS), перед отправкой фактического HTTP-запроса.
Этот обратный вызов может быть удобен в ситуациях, когда приложению необходимо определить, следует ли обрабатывать соединение в зависимости от IP-адреса и порта источника и получателя.
Некоторые из вариантов использования включают:
- Блокирование запросов к IP-адресам внутренней сети
- Блокирование запросов к IP-адресам, принадлежащим странам или сетям, находящимся под санкциями.
- Разрешение запросов только к известному списку IP-адресов, но когда адреса DNS могут меняться.
Новые константы
Эта функция добавляет три новые константы:
CURLOPT_PREREQFUNCTION:intприсвоенное значение20312, опция Curl дляcurl_setopt.CURL_PREREQFUNC_OK:intприсвоенное значение1, возможное возвращаемое значение для обратного вызова, чтобы разрешить запрос.CURL_PREREQFUNC_ABORT:intприсвоенное значение0, возможное возвращаемое значение для обратного вызова, чтобы прервать запрос.
Параметр Curl CURLOPT_PREREQFUNCTION
Опция CURLOPT_PREREQFUNCTION принимает callable и должна возвращать CURL_PREREQFUNC_OK или CURL_PREREQFUNC_ABORT для разрешения или прерывания запроса.
callable вызывается с объектом CurlHandle, IP-адресом назначения, IP-адресом источника (локальным), номером удалённого порта и номером порта источника (локального).
Если соединение используется повторно или запрос следует за HTTP-перенаправлением, возможно, что обратный вызов будет вызван несколько раз.
function check_is_not_local_ip_address(
\CurlHandle $ch,
string $destination_ip,
string $local_ip,
int $destination_port,
int $local_port
): int {
$isGlobalIP = filter_var($destination_ip, FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE) !== false;
return $isGlobalIP
? CURL_PREREQFUNC_OK
: CURL_PREREQFUNC_ABORT;
}
$ch = curl_init('https://php.watch');
curl_setopt($ch, CURLOPT_PREREQFUNCTION, 'check_is_not_local_ip_address');- Если обратный вызов
CURLOPT_PREREQFUNCTIONне возвращает никакого значения, будет выброшеноTypeError. - Если
CURLOPT_PREREQFUNCTIONвозвращает значениеint, отличное отCURL_PREREQFUNC_OKилиCURL_PREREQFUNC_ABORT, то будет выброшеноValueError.
Оба исключения несут обратный вызов CURLOPT_PREREQFUNCTION, который должен вернуть либо CURL_PREREQFUNC_OK, либо CURL_PREREQFUNC_ABORT в качестве сообщения об ошибке. В обоих случаях обратный вызов будет прерван.
Если запрос Curl прерывается callable CURLOPT_PREREQFUNCTION, запрос Curl завершается с ошибкой CURLE_ABORTED_BY_CALLBACK:
$ch = curl_init('https://php.watch');
curl_setopt($ch, CURLOPT_PREREQFUNCTION, static fn($x): int => CURL_PREREQFUNC_ABORT);
curl_exec($ch);
echo curl_error($ch); // "операция прервана обратным вызовом предварительного запроса"
echo curl_errno($ch); // CURLE_ABORTED_BY_CALLBACK (int 42)После установки обратного вызова его можно удалить, установив значение null:
curl_setopt($ch, CURLOPT_PREREQFUNCTION, null);Влияние на обратную совместимость
CURLOPT_PREREQFUNCTION, CURL_PREREQFUNC_OK и CURL_PREREQFUN`C_ABORT — новые глобальные константы PHP. Поскольку эта функция требует внутренней обработки на уровне расширения PHP Curl, её невозможно перенести на старые версии PHP.