[php] PHP cURL이 단일 요청으로 응답 헤더와 본문을 검색 할 수 있습니까?

PHP를 사용하여 cURL 요청을 위해 헤더와 본문을 모두 얻는 방법이 있습니까? 나는이 옵션을 발견했다 :

curl_setopt($ch, CURLOPT_HEADER, true);

본문과 헤더 를 반환 하지만 본문을 얻으려면 구문 분석해야합니다. 보다 유용하고 안전한 방법으로 둘 다 얻을 수있는 방법이 있습니까?

“단일 요청”의 경우 GET / POST 이전에 HEAD 요청을 발행하지 않는 것을 의미합니다.



답변

이에 대한 한 가지 해결책은 PHP 문서 주석에 게시되어 있습니다. http://www.php.net/manual/en/function.curl-exec.php#80442

코드 예 :

$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
// ...

$response = curl_exec($ch);

// Then, after your curl_exec call:
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);

경고 : 아래 설명에 명시된 바와 같이 프록시 서버와 함께 사용하거나 특정 유형의 리디렉션을 처리 할 때는 신뢰할 수 없습니다. @Geoffrey의 답변은 이러한 것들을보다 안정적으로 처리 할 수 ​​있습니다.


답변

이 스레드를 제공하는 다른 많은 솔루션 이 올바르게 수행 하지 않습니다 .

  • 서버가 켜져 있거나 서버가 100 코드로 응답 할 \r\n\r\n때는 스 플리 팅을 신뢰할 수 없습니다 CURLOPT_FOLLOWLOCATION.
  • 모든 서버가 표준을 준수하는 것은 아니며 \n새로운 회선에 대해서만 전송 합니다.
  • CURLINFO_HEADER_SIZE특히 프록시가 사용되거나 일부 동일한 리디렉션 시나리오 에서 헤더 크기를 감지하는 것이 항상 신뢰할 수있는 것은 아닙니다.

가장 올바른 방법은 CURLOPT_HEADERFUNCTION입니다.

다음은 PHP 클로저를 사용하여이를 수행하는 매우 깨끗한 방법입니다. 또한 서버와 HTTP 버전에서 일관된 처리를 위해 모든 헤더를 소문자로 변환합니다.

이 버전은 중복 된 헤더를 유지합니다

이것은 RFC822 및 RFC2616을 준수합니다. mb_문자열 기능 을 사용하기 위해 편집을 제안하지 마십시오 . 올바르지 않습니다!

$ch = curl_init();
$headers = [];
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// this function is called by curl for each header received
curl_setopt($ch, CURLOPT_HEADERFUNCTION,
  function($curl, $header) use (&$headers)
  {
    $len = strlen($header);
    $header = explode(':', $header, 2);
    if (count($header) < 2) // ignore invalid headers
      return $len;

    $headers[strtolower(trim($header[0]))][] = trim($header[1]);

    return $len;
  }
);

$data = curl_exec($ch);
print_r($headers);


답변

Curl에는 CURLOPT_HEADERFUNCTION이라는 옵션이 내장되어 있습니다. 이 옵션의 값은 콜백 함수의 이름이어야합니다. Curl은 헤더 (및 헤더 만!)를이 콜백 함수에 한 줄씩 전달합니다 (따라서 헤더 섹션의 맨 위에서 시작하여 각 헤더 행에 대해 함수가 호출됩니다). 콜백 함수는 그와 함께 무엇이든 할 수 있습니다 (그리고 주어진 줄의 바이트 수를 반환해야합니다). 테스트 된 작업 코드는 다음과 같습니다.

function HandleHeaderLine( $curl, $header_line ) {
    echo "<br>YEAH: ".$header_line; // or do whatever
    return strlen($header_line);
}


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://www.google.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADERFUNCTION, "HandleHeaderLine");
$body = curl_exec($ch); 

위의 내용은 모든 프로토콜과 프록시에서도 작동하며 헤더 크기에 대해 걱정하거나 다른 컬 옵션을 많이 설정할 필요가 없습니다.

추신 : 객체 메소드로 헤더 라인을 처리하려면 다음을 수행하십시오.

curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$object, 'methodName'))


답변

이것이 당신이 찾고있는 것입니까?

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


답변

옵션을 설정하십시오.

  • CURLOPT_HEADER, 0

  • CURLOPT_RETURNTRANSFER, 1

CURLINFO_HTTP_CODE와 함께 curl_getinfo를 사용하십시오 (또는 opt 매개 변수가 없으면 원하는 모든 정보가 포함 된 연관 배열이 있습니다)

자세한 내용은 http://php.net/manual/fr/function.curl-getinfo.php


답변

을 구체적으로 원한다면 Content-Type특별한 cURL 옵션을 사용하여 검색하십시오.

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
$content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);


답변

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 Continue다른 헤더 앞에 작동합니다 .

CRLF 대신 LF 만 줄 바꿈으로 보내는 버그가있는 서버로 작업해야하는 경우 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);