在正文前缀之后停止 PHP cURL 传输
在写入回调中保留一段有上限的前缀,并且只把该回调故意造成的写入错误视为预期结果。
cURL 的写入回调可以保留一段有上限的正文前缀,并在达到该上限时停止传输。用你自己的标志来区分这种有意停止和另一种写入失败。
对于目标 URL 已经配置好的新句柄:
$limit = 32768;
$prefix = '';
$limitReached = false;
curl_setopt_array($ch, [
CURLOPT_PROXY => 'socks5h://proxy.example.net:1080',
CURLOPT_HEADER => false,
CURLOPT_WRITEFUNCTION => function ($handle, $chunk)
use (&$prefix, &$limitReached, $limit) {
$remaining = $limit - strlen($prefix);
$prefix .= substr($chunk, 0, $remaining);
if (strlen($prefix) >= $limit) {
$limitReached = true;
return 0;
}
return strlen($chunk);
},
]);
$result = curl_exec($ch);
$error = curl_errno($ch);
$expectedStop = $limitReached && $error === CURLE_WRITE_ERROR;
if ($result === false && !$expectedStop) {
throw new RuntimeException(curl_error($ch), $error);
}
代理 URL 的 socks5h 方案要求由代理解析目标主机名。在所示的新句柄上做允许的公开目标测试时,SOCKS5 代理列表中无需账户的条目可以提供该端点。TLS 证书校验保持其常规设置。
对非空数据块返回零会告诉 libcurl 回调没有接受所提供的数据。它会以 CURLE_WRITE_ERROR 中止。这里只有该错误与回调的 limitReached 标志同时出现才被视为预期。
短于上限的响应会正常结束。达到或超过上限时,即使最后一次回调收到更大的数据块,prefix 最多也只保留 32 KiB。回调的数据块大小会变化;请求的缓冲区大小并不保证调用长度固定。
这限制的是被保留的正文,而不是连接上已经缓冲或传输的每一个字节。前缀可能在多字节字符、JSON 值或 HTML 元素中间结束,因此不要假定它是完整可解析的文档。