10、PHP 8.4 新特性 - cURL 扩展 setopt 新增 CURLOPT_DEBUGFUNCTION 选项
注意:目前文档还没有更此说明,通过代码追踪可以看到这是 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 都将支持这一功能。