我遇到一个问题,一旦curl被显式设置为使用CURLOPT_HEADER,我从REST端点(SugarCRM 7)获得的所有响应都将包含完整的HTTP Header。我这样做了所以我可以获取并存储Cookie用于会话管理,但直接的缺点是我从curl_exec()收到的响应是它包含所有标头,有效地破坏了将返回结果解释为有效JSON的任何尝试。 POST呼叫的实际响应发布在下面。
"HTTP/1.1 200 OK
Date: Thu, 25 Feb 2016 03:23:35 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.1e-fips mod_fcgid/2.3.9 PHP/5.4.16
X-Powered-By: PHP/5.4.16
Set-Cookie: PHPSESSID=f0bsbjelfa9c0ada7qj1816986; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 75
Content-Type: application/json; charset=UTF-8
{"examplekey":"examplevalue"}"
如果禁用了CURLOPT_HEADER,则响应会发送一个有效的JSON对象,但是没有有效的方法来跟踪会话的生命周期。通过拆分CRLF来提取JSON数据应该是相当可预测的,但必须有一种方法让cURL同时发送正文响应和标题(cookie和所有),而不必冒险使用regexing CRLFs整个回应。不幸的是,如果没有禁用CURLOPT_HEADER,我没有运气访问cookie。
总结一下 - 从cURL请求中保留标头的最佳方法是什么,同时保留我可以处理的有效JSON序列化字符串?
以下是此过程使用的方法。
public function RunCurl() {
ob_start();
//Set x-www-form-urlencoded header
$Headers[] = 'Content-Type: application/x-www-form-urlencoded';
$Headers[] = 'cache-control: no-cache';
curl_setopt($this->CurlRequest, CURLOPT_VERBOSE, true);
curl_setopt($this->CurlRequest, CURLOPT_URL, $this->SourceURL);
curl_setopt($this->CurlRequest, CURLOPT_HEADER, 1);
curl_setopt($this->CurlRequest, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($this->CurlRequest, CURLOPT_POSTFIELDS, http_build_query($this->EncapsulatedPostData));
curl_setopt($this->CurlRequest, CURLOPT_HEADER, 1);
curl_setopt($this->CurlRequest, CURLOPT_HTTPHEADER, $this->Cookie);
try {
$Results = curl_exec($this->CurlRequest);
preg_match_all('/^Set-Cookie:\s*([^\r\n]*)/mi', $Results, $ms);
$this->Cookie = $ms;
curl_close($this->CurlRequest);
} catch (Exception $ex) {
echo 'Caught exception: ', $ex->getMessage(), "\n";
return false;
}
ob_end_flush();
return json_decode(utf8_decode($Results));
}
答案 0 :(得分:1)
另一种方法是使用CURLOPT_HEADERFUNCTION
选项 - 这允许您将标头发送到回调函数。一个快速的例子应该接近你所追求的内容如下:
public function RunCurl() {
ob_start();
//Set x-www-form-urlencoded header
$Headers[] = 'Content-Type: application/x-www-form-urlencoded';
$Headers[] = 'cache-control: no-cache';
curl_setopt($this->CurlRequest, CURLOPT_VERBOSE, true);
curl_setopt($this->CurlRequest, CURLOPT_URL, $this->SourceURL);
curl_setopt($this->CurlRequest, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($this->CurlRequest, CURLOPT_POSTFIELDS, http_build_query($this->EncapsulatedPostData));
curl_setopt($this->CurlRequest, CURLOPT_HTTPHEADER, $this->Cookie);
curl_setopt($this->CurlRequest, CURLOPT_HEADERFUNCTION, array($this, 'readHeader'));
try {
$Results = curl_exec($this->CurlRequest);
curl_close($this->CurlRequest);
} catch (Exception $ex) {
echo 'Caught exception: ', $ex->getMessage(), "\n";
return false;
}
ob_end_flush();
return json_decode(utf8_decode($Results));
}
private function readHeader($ch, $header) {
$found = preg_match_all('/^Set-Cookie:\s*([^\r\n]*)/mi', $header, $ms);
if ($found !== 0) {
$this->Cookie = $ms;
}
return strlen($header);
}
答案 1 :(得分:1)
在curl_exec
Body将包含您的json响应后添加这两行。
$Results = curl_exec($this->CurlRequest);
$header_size = curl_getinfo($this->CurlRequest, CURLINFO_HEADER_SIZE);
$body = substr($Results, $header_size);
答案 2 :(得分:0)
根据HTTP Specification (RFC7230),CRLF(“\ r \ n \ r \ n”)用作标题和正文部分的分隔符。 因此,您可以通过以下方式获取响应的正文部分:
$body = substr($response, strpos($response, "\r\n\r\n")+4);
或
list($header, $body) = explode("\r\n\r\n", $response, 2);