9、PHP 8.4 新特性 - cURL 扩展 setopt 新增 CURLOPT_PREREQFUNCTION 选项

作者: 温新

图书: 【PHP 8.4 新特性】

阅读: 128

时间: 2025-02-11 02:19:21

注意:目前文档还没有更此说明,通过代码追踪可以看到这是 PHP 8.4 新增的。

PHP 8.4 引入了 CURLOPT_PREREQFUNCTION 选项,这是 cURL 扩展中的一个新功能,允许你在请求执行之前调用一个预处理函数。此选项需要使用 libcurl 7.80.0 或更高版本构建的 PHP 8.4 才可用。

CURLOPT_PREREQFUNCTION 回调函数在初始连接建立之后、请求发送之前被调用。例如,在 HTTPS 请求中,该 CURLOPT_PREREQFUNCTION 回调会在 HTTPS 连接(包括 DNS 解析、TCP 连接和 TLS 握手)建立完成但实际的 HTTP 请求发送之前被触发。

这个回调在应用程序需要根据源地址和目标地址的 IP 地址及端口号来判断是否继续处理连接的情况下非常有用。

一些使用场景包括:

  • 阻止向内网 IP 地址发起请求。
  • 阻止向受制裁国家或网络中的 IP 地址发起请求。
  • 仅允许向已知的 IP 地址列表发起请求,即使这些 IP 的域名可能变化。

新增常量

  • CURLOPT_PREREQFUNCTION:整数 20312,用于 curl_setopt 函数的 cURL 选项。通过设置这个选项,你可以指定一个回调函数,该函数将在初始连接建立后但在实际请求发送之前被调用。
  • CURL_PREREQFUNC_OK:整数 1,这是回调函数的一个可能返回值。如果回调函数返回此值,则表示允许继续处理当前请求。
  • CURL_PREREQFUNC_ABORT:整数 0,这也是回调函数的一个可能返回值。如果回调函数返回此值,则会中断当前请求,阻止其进一步执行。

CURLOPT_PREREQFUNCTION 选项

CURLOPT_PREREQFUNCTION 选项接受一个可调用对象(例如函数),并且该函数必须返回 CURL_PREREQFUNC_OKCURL_PREREQFUNC_ABORT 来决定是否允许或中止请求。此回调函数在被调用时会接收到几个参数,包括 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://ziruchu.com');
curl_setopt($ch, CURLOPT_PREREQFUNCTION, 'check_is_not_local_ip_address');

如果 CURLOPT_PREREQFUNCTION 回调函数没有返回任何值,将会抛出一个 TypeError

如果 CURLOPT_PREREQFUNCTION 返回了一个既不是 CURL_PREREQFUNC_OK 也不是 CURL_PREREQFUNC_ABORT 的整数值,将会抛出一个 ValueError

这两种异常都会携带错误信息:“CURLOPT_PREREQFUNCTION 回调必须返回 CURL_PREREQFUNC_OKCURL_PREREQFUNC_ABORT”。在这两种情况下,回调都将被中止。

案例

<?php

// 初始化 cURL 会话
$ch = curl_init('https://ziruchu.com');

// 定义预处理函数
function prereq_function($ch) {
    // 在这里你可以对请求进行修改或验证
    // 比如添加一个自定义的请求头
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-Custom-Header: Value']);
    
    // 你可以在这里返回 true 或 false,来决定是否继续请求
    // 如果返回 false,cURL 请求将不会被执行
    return true;
}

// 设置 CURLOPT_PREREQFUNCTION 选项
curl_setopt($ch, CURLOPT_PREREQFUNCTION, 'prereq_function');

$response = curl_exec($ch);
curl_close($ch);

echo $response;
请登录后再评论