2016-02-25 2 views
0

Я столкнулся с проблемой, когда один раз curl явно настроен на использование CURLOPT_HEADER, все ответы, которые я получаю из конечной точки REST (SugarCRM 7), будут содержать полный HTTP-заголовок. Я сделал это, чтобы я мог получать и хранить Cookies для управления сеансом, но ближайший недостаток - это ответ, который я получаю от curl_exec(), так это то, что он включает все заголовки, эффективно нарушая любую попытку интерпретировать возвращенный результат как действительный JSON. Фактический ответ на вызов POST размещен ниже.php curl Response включает HTTP-заголовок в ответе JSON

"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, но не эффективный способ отслеживания жизни сессии. Должно быть достаточно предсказуемо вытащить данные JSON из-за разделения на CRLF, но должен быть способ, чтобы cURL отправлял как ответ тела, так и заголовки (куки-файлы и все) без необходимости рисковать с регулярными выражениями CRLF с весь ответ. К сожалению, мне не удалось получить доступ к файлам cookie без отключения CURLOPT_HEADER.

Подводя итог - что было бы лучшим подходом к сохранению заголовков из запроса 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

Согласно HTTP Specification (RFC7230), CRLF ("\ г \ п \ г \ п") используется в качестве разделителя для разделов заголовка и тела. Таким образом, вы можете получить корпусную часть ответа просто:

$body = substr($response, strpos($response, "\r\n\r\n")+4); 

или

list($header, $body) = explode("\r\n\r\n", $response, 2); 
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

Добавить эти две строки после curl_exec тела будет содержать ответ JSon.

$Results = curl_exec($this->CurlRequest); 

$header_size = curl_getinfo($this->CurlRequest, CURLINFO_HEADER_SIZE); 
$body = substr($Results, $header_size); 
+1

Вам просто нужно следить за некоторые версии завитка [неправильно обрабатывающего размер заголовка, когда есть прокси] (http://stackoverflow.com/questions/34743545/php-curl-incorrect-header- размера, когда использование прокси) –