是否有任何方法来获得头部和主体的cURL请求使用PHP?我发现这个选项:

curl_setopt($ch, CURLOPT_HEADER, true);

会返回body和header,但之后我需要解析它来得到body。有没有办法以更可用(和更安全)的方式同时获得两者?

注意,对于“单个请求”,我的意思是避免在GET/POST之前发出HEAD请求。


当前回答

以防你不能/不使用CURLOPT_HEADERFUNCTION或其他解决方案;

$nextCheck = function($body) {
    return ($body && strpos($body, 'HTTP/') === 0);
};

[$headers, $body] = explode("\r\n\r\n", $result, 2);
if ($nextCheck($body)) {
    do {
        [$headers, $body] = explode("\r\n\r\n", $body, 2);
    } while ($nextCheck($body));
}

其他回答

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);

$parts = explode("\r\n\r\nHTTP/", $response);
$parts = (count($parts) > 1 ? 'HTTP/' : '').array_pop($parts);
list($headers, $body) = explode("\r\n\r\n", $parts, 2);

适用于HTTP/1.1 100在其他报头之前继续。

如果你需要使用错误服务器,只发送LF而不是CRLF作为换行符,你可以使用preg_split,如下所示:

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);

$parts = preg_split("@\r?\n\r?\nHTTP/@u", $response);
$parts = (count($parts) > 1 ? 'HTTP/' : '').array_pop($parts);
list($headers, $body) = preg_split("@\r?\n\r?\n@u", $parts, 2);

这就是你想要的吗?

curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
$response = curl_exec($ch); 
list($header, $body) = explode("\r\n\r\n", $response, 2);

如果你正在使用GET,试试这个:

$curl = curl_init($url);

curl_setopt_array($curl, array(
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET",
    CURLOPT_HTTPHEADER => array(
        "Cache-Control: no-cache"
    ),
));

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

只需设置选项:

CURLOPT_HEADER, 0岁 CURLOPT_RETURNTRANSFER, 1

并使用curl_getinfo与CURLINFO_HTTP_CODE(或没有opt参数,你将有一个与所有你想要的信息的关联数组)

更多信息请访问:http://php.net/manual/fr/function.curl-getinfo.php

这里的许多答案的问题是“\r\n\r\n”可以合法地出现在html的主体中,因此您不能确保正确地分割了头文件。

在调用curl_exec时单独存储标头的唯一方法似乎是使用回调,就像上面https://stackoverflow.com/a/25118032/3326494中建议的那样

然后,为了(可靠地)获得请求的主体,您需要将Content-Length报头的值作为负起始值传递给substr()。