10、PHP 8.4 新特性 - cURL 扩展 setopt 新增 CURLOPT_DEBUGFUNCTION 选项

作者: 温新

图书: 【PHP 8.4 新特性】

阅读: 96

时间: 2025-01-17 10:09:14

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

在 PHP 8.4 中,cURL 扩展新增了 CURLOPT_DEBUGFUNCTION 选项,允许开发者设置一个回调函数来捕获和处理 cURL 请求的调试信息。这为调试和分析 cURL 请求提供了更多的灵活性,尤其是对于复杂的 HTTP 请求或者接口调试。

新增常量

CURLOPT_DEBUGFUNCTION:整数 20094,是 curl_setopt 函数的一个选项。

调试信息类型

回调函数会被调用,并且会接收到一个整数值,该值是以下常量之一,用于指示传递给下一个参数的数据类型。

常量 说明
CURLINFO_TEXT 信息文本
CURLINFO_HEADER_IN 从对端接收到的头部(或类似头部)数据
CURLINFO_HEADER_OUT 发送到对端的头部(或类似头部)数据
CURLINFO_DATA_IN 从对端接收到的未经处理的协议数据。即使数据被编码或压缩,也不会在此回调中提供解码或解压缩后的数据
CURLINFO_DATA_OUT 发送到对端的协议数据
CURLINFO_SSL_DATA_IN 从对端接收到的 SSL/TLS(二进制)数据
CURLINFO_SSL_DATA_OUT 发送到对端的 SSL/TLS(二进制)数据

请注意,CURLINFO_HEADER_OUT 常量已经在之前的 PHP 版本中存在。有关与 CURLINFO_HEADER_OUT 一起使用的更多细节,请参阅相关文档。

CURLOPT_DEBUGFUNCTION 选项

CURLOPT_DEBUGFUNCTION cURL 选项接受一个可调用值,每当 cURL 发出调试信息时,该可调用值就会被调用。为了让回调函数能够被调用,还需要启用 CURLOPT_VERBOSE 选项。

如果未启用 CURLOPT_VERBOSE,则 CURLOPT_DEBUGFUNCTION 回调将完全不会被调用。

CURLOPT_DEBUGFUNCTION 回调可以采用以下签名:

function foo(CurlHandle $curlHandle, int $type, string $data): void {}
  • CurlHandle $curlHandle:cURL 句柄对象。
  • int $type:指示传递的调试信息类型。请参阅调试信息类型部分获取解释。
  • string $data:实际的调试信息。
<?php

declare(strict_types=1);

$ch = curl_init('https://ziruchu.com');
curl_setopt($ch, CURLOPT_DEBUGFUNCTION,
    static function(CurlHandle $ch, int $type, string $data): void {
        printf("Debug (%d): %s", $type, $data);
    }
);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_exec($ch);

输出

Debug (0):   Trying 42.193.250.235:443...
Debug (0): Connected to ziruchu.com (42.193.250.235) port 443 (#0)
Debug (0): ALPN, offering h2
Debug (0): ALPN, offering http/1.1
Debug (0):  CAfile: /etc/pki/tls/certs/ca-bundle.crt
Debug (0): TLSv1.0 (OUT), TLS header, Certificate Status (22):
Debug (6): Debug (0): TLSv1.3 (OUT), TLS handshake, Client hello (1):

...

可调用对象的返回值将被忽略。

使用 CURLINFO_HEADER_OUT

注意,PHP 的 cURL 扩展提供了一个名为 CURLINFO_HEADER_OUT 的非标准选项,该选项可以返回 cURL 请求的输出头部。这并不是 libcurl 的一部分,但 cURL 扩展利用了 CURLOPT_DEBUGFUNCTION 这个 libcurl 选项来捕获 CURLINFO_HEADER_OUT 数据,并通过 curl_getinfo 函数返回这些数据。

这种行为是有问题的,因为它打破了使用 CURLINFO_ 常量作为 cURL 选项的模式。此外,启用 CURLINFO_HEADER_OUT "选项" 会隐式地启用 CURLOPT_VERBOSE

为了确保向后兼容性,在设置了 CURLOPT_DEBUGFUNCTION 选项之后不允许再启用 CURLINFO_HEADER_OUT 选项,这样做会导致抛出一个 ValueError 异常:

$ch = curl_init();
curl_setopt($ch, CURLOPT_DEBUGFUNCTION,static function() {});
curl_setopt($ch, CURLINFO_HEADER_OUT, true);

ValueError: CURLINFO_HEADER_OUT option must not be set when the CURLOPT_DEBUGFUNCTION option is set

允许在 CURLINFO_HEADER_OUT 之后设置 CURLOPT_DEBUGFUNCTION 选项,并覆盖 CURLINFO_HEADER_OUT 选项。

使用案例

<?php

declare(strict_types=1);

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

// 定义调试回调函数
function debug_function($ch, $type, $data) {
    echo '调试开始' . PHP_EOL;
    // 打印调试信息
    echo "Type: $type\n";
    echo "Data: $data\n";
    // 返回 true 表示继续执行 cURL 请求
    return true;
}

// 设置 CURLOPT_DEBUGFUNCTION 选项
curl_setopt($ch, CURLOPT_DEBUGFUNCTION, 'debug_function');
// 设置 CURLOPT_VERBOSE 以启用调试模式
curl_setopt($ch, CURLOPT_VERBOSE, true);
$response = curl_exec($ch);
curl_close($ch);

echo $response;

输出

调试开始
Type: 0
Data:   Trying 113.108.81.189:443...

调试开始
Type: 0
Data: Connected to qq.com (113.108.81.189) port 443 (#0)

...

向后兼容性影响

CURLOPT_DEBUGFUNCTION 及其相关的一系列常量是 PHP 8.4 中新增的。CURLOPT_DEBUGFUNCTION 选项是在 libcurl 7.9.6 版本中添加到 libcurl 的,而由于 PHP 8.4 要求使用 libcurl 7.61.0 或更高版本,因此所有基于 PHP 8.4 构建的 cURL 都将支持这一功能。

请登录后再评论