0

CURLOPT_HEADER を使用するように curl を明示的に設定すると、REST エンドポイント (SugarCRM 7) から取得するすべての応答に完全な HTTP ヘッダーが含まれるという問題が発生しています。これを行ったのは、セッション管理用の 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 データを引き出すことはかなり予測可能ですが、CRLF を全体の応答。残念ながら、CURLOPT_HEADER を無効にしないと Cookie にアクセスできませんでした。

要約すると、処理できる有効な JSON シリアル化された文字列を残しながら、cURL 要求からのヘッダーを保持するための最良の方法は何でしょうか?

以下は、このプロセスに使用されている方法です。

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));
}
4

3 に答える 3

2

Bodyの後にこれらの 2 行を追加しcurl_execて、json 応答を含めます。

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

$header_size = curl_getinfo($this->CurlRequest, CURLINFO_HEADER_SIZE);
$body = substr($Results, $header_size);
于 2016-02-25T05:38:53.943 に答える
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);
}
于 2016-02-25T05:10:09.223 に答える
0

HTTP 仕様 (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);
于 2016-02-25T04:50:46.330 に答える