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.