복붙노트

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

PHP

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

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

curl_setopt($ch, CURLOPT_HEADER, true);

본문과 머리글을 반환 할 것이지만, 그 다음 본문을 가져 오기 위해 구문 분석해야합니다. 더 유용한 (그리고 안전한) 방법으로 둘 다 얻을 수있는 방법이 있습니까?

"단일 요청"의 경우 GET / POST 이전에 HEAD 요청을 피하는 것을 의미합니다.

해결법

  1. ==============================

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

    이에 대한 한 가지 해결책은 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의 답변이 더 안정적으로 처리 할 수 ​​있습니다.

  2. ==============================

    2.Curl에는 CURLOPT_HEADERFUNCTION이라는 내장 옵션이 있습니다. 이 옵션의 값은 콜백 함수의 이름이어야합니다. Curl은 헤더 (및 헤더 만!)를이 콜백 함수에 줄 단위로 전달합니다 (따라서 헤더 섹션의 맨 위에서 시작하여 각 헤더 행에 대해 함수가 호출됩니다). 그런 다음 콜백 함수는 모든 작업을 수행 할 수 있으며 주어진 행의 바이트 수를 반환해야합니다. 다음은 테스트 된 작업 코드입니다.

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

    위의 모든 것은 다른 프로토콜과 프록시에서도 작동합니다. 헤더 크기에 대해 걱정할 필요가 없으며 다양한 컬 옵션을 설정해야합니다.

    P.S. : 객체 메소드를 사용하여 헤더 행을 처리하려면 다음을 수행하십시오.

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

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

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

    가장 올바른 방법은 CURLOPT_HEADERFUNCTION을 사용하는 것입니다.

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

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

    이것은 RFC 822 및 RFC 2616을 준수합니다. mb_string 함수를 사용하기 위해 편집을 제안하지 마십시오. 잘못된 것입니다!

    $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;
    
        $name = strtolower(trim($header[0]));
        if (!array_key_exists($name, $headers))
          $headers[$name] = [trim($header[1])];
        else
          $headers[$name][] = trim($header[1]);
    
        return $len;
      }
    );
    
    $data = curl_exec($ch);
    print_r($headers);
    
  4. ==============================

    4.너는 무엇을보고 있니?

    너는 무엇을보고 있니?

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

    5.그냥 옵션을 설정하십시오 :

    그냥 옵션을 설정하십시오 :

    curl_getinfo를 CURLINFO_HTTP_CODE (또는 opt 매개 변수 없음)와 함께 사용하면 원하는 모든 정보가 포함 된 연관 배열이됩니다.

    더보기 : http://php.net/manual/fr/function.curl-getinfo.php

  6. ==============================

    6.특별히 Content-Type을 원한다면 검색 할 수있는 특별한 cURL 옵션이 있습니다.

    특별히 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);
    
  7. ==============================

    7.

    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 다른 헤더보다 먼저 계속하십시오.

    줄 바꿈으로 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);
    
  8. ==============================

    8.내 길은 ~이다.

    내 길은 ~이다.

    $response = curl_exec($ch);
    $x = explode("\r\n\r\n", $v, 3);
    $header=http_parse_headers($x[0]);
    if ($header=['Response Code']==100){ //use the other "header"
        $header=http_parse_headers($x[1]);
        $body=$x[2];
    }else{
        $body=$x[1];
    }
    

    필요한 경우 for 루프를 적용하고 분해 한계를 제거하십시오.

  9. ==============================

    9.여기에 많은 해답이있는 문제는 "\ r \ n \ r \ n"이 html 본문에 합법적으로 나타날 수 있기 때문에 헤더를 올바르게 분할하지 못한다는 것입니다.

    여기에 많은 해답이있는 문제는 "\ r \ n \ r \ n"이 html 본문에 합법적으로 나타날 수 있기 때문에 헤더를 올바르게 분할하지 못한다는 것입니다.

    curl_exec에 대한 하나의 호출로 헤더를 별도로 저장하는 유일한 방법은 https://stackoverflow.com/a/25118032/3326494에서 위에 제안 된 콜백을 사용하는 것입니다.

    그런 다음 (확실하게) 요청 본문을 가져 오려면 Content-Length 헤더 값을 음수 시작 값으로 substr ()에 전달해야합니다.

  10. ==============================

    10.서버에서 반환 된 마지막 물건이 필요할 때 조심하십시오. 이 코드는 실제 (마지막) 헤더와 본문을 기다리는 동안 기대치를 낮출 수 있습니다. list ($ headers, $ body) = explode ( "\ r \ n \ r \ n", $ result, 2);

    서버에서 반환 된 마지막 물건이 필요할 때 조심하십시오. 이 코드는 실제 (마지막) 헤더와 본문을 기다리는 동안 기대치를 낮출 수 있습니다. list ($ headers, $ body) = explode ( "\ r \ n \ r \ n", $ result, 2);

    여기에 최종 헤더 및 본문 부분을 가져 오는 간단한 방법이 있습니다.

    $result = explode("\r\n\r\n", $result);
    
    // drop redirect etc. headers
    while (count($result) > 2) {
        array_shift($result);
    }
    
    // split headers / body parts
    @ list($headers, $body) = $result;
    
  11. ==============================

    11.참조 매개 변수를 사용하여 응답 헤더를 반환합니다.

    참조 매개 변수를 사용하여 응답 헤더를 반환합니다.

    <?php
    $data=array('device_token'=>'5641c5b10751c49c07ceb4',
                'content'=>'测试测试test'
               );
    $rtn=curl_to_host('POST', 'http://test.com/send_by_device_token', array(), $data, $resp_headers);
    echo $rtn;
    var_export($resp_headers);
    
    function curl_to_host($method, $url, $headers, $data, &$resp_headers)
             {$ch=curl_init($url);
              curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $GLOBALS['POST_TO_HOST.LINE_TIMEOUT']?$GLOBALS['POST_TO_HOST.LINE_TIMEOUT']:5);
              curl_setopt($ch, CURLOPT_TIMEOUT, $GLOBALS['POST_TO_HOST.TOTAL_TIMEOUT']?$GLOBALS['POST_TO_HOST.TOTAL_TIMEOUT']:20);
              curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
              curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
              curl_setopt($ch, CURLOPT_HEADER, 1);
    
              if ($method=='POST')
                 {curl_setopt($ch, CURLOPT_POST, true);
                  curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
                 }
              foreach ($headers as $k=>$v)
                      {$headers[$k]=str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $k)))).': '.$v;
                      }
              curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
              $rtn=curl_exec($ch);
              curl_close($ch);
    
              $rtn=explode("\r\n\r\nHTTP/", $rtn, 2);    //to deal with "HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK...\r\n\r\n..." header
              $rtn=(count($rtn)>1 ? 'HTTP/' : '').array_pop($rtn);
              list($str_resp_headers, $rtn)=explode("\r\n\r\n", $rtn, 2);
    
              $str_resp_headers=explode("\r\n", $str_resp_headers);
              array_shift($str_resp_headers);    //get rid of "HTTP/1.1 200 OK"
              $resp_headers=array();
              foreach ($str_resp_headers as $k=>$v)
                      {$v=explode(': ', $v, 2);
                       $resp_headers[$v[0]]=$v[1];
                      }
    
              return $rtn;
             }
    ?>
    
  12. ==============================

    12.curl을 사용할 필요가 없다면;

    curl을 사용할 필요가 없다면;

    $body = file_get_contents('http://example.com');
    var_export($http_response_header);
    var_export($body);
    

    어느 출력

    array (
      0 => 'HTTP/1.0 200 OK',
      1 => 'Accept-Ranges: bytes',
      2 => 'Cache-Control: max-age=604800',
      3 => 'Content-Type: text/html',
      4 => 'Date: Tue, 24 Feb 2015 20:37:13 GMT',
      5 => 'Etag: "359670651"',
      6 => 'Expires: Tue, 03 Mar 2015 20:37:13 GMT',
      7 => 'Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT',
      8 => 'Server: ECS (cpm/F9D5)',
      9 => 'X-Cache: HIT',
      10 => 'x-ec-custom-error: 1',
      11 => 'Content-Length: 1270',
      12 => 'Connection: close',
    )'<!doctype html>
    <html>
    <head>
        <title>Example Domain</title>...
    

    http://php.net/manual/en/reserved.variables.httpresponseheader.php를 참조하십시오.

  13. from https://stackoverflow.com/questions/9183178/can-php-curl-retrieve-response-headers-and-body-in-a-single-request by cc-by-sa and MIT license