क्या PHP कर्ल एक ही अनुरोध में प्रतिक्रिया शीर्षलेख और शरीर को पुनर्प्राप्त कर सकता है?




http curl (8)

PHP का उपयोग कर एक curl अनुरोध के लिए दोनों शीर्षलेख और शरीर को पाने का कोई तरीका है? मैंने पाया कि यह विकल्प:

curl_setopt($ch, CURLOPT_HEADER, true);

शरीर और हेडर को वापस करने जा रहा है, लेकिन फिर मुझे शरीर को पाने के लिए इसे पार्स करने की आवश्यकता है। क्या अधिक उपयोगी (और सुरक्षित) तरीके से दोनों को पाने का कोई तरीका है?

ध्यान दें कि "एकल अनुरोध" के लिए मेरा मतलब है जीईटी / पोस्ट से पहले एक हेड अनुरोध जारी करना।


इस धागे की पेशकश के कई अन्य समाधान इस सही तरीके से नहीं कर रहे हैं।

  • \r\n\r\n पर विभाजित विश्वसनीय नहीं है जब CURLOPT_FOLLOWLOCATION है या जब सर्वर 100 कोड के साथ प्रतिक्रिया करता है।
  • सभी सर्वर मानकों के अनुरूप नहीं हैं और नई लाइनों के लिए सिर्फ एक \n संचारित करते हैं।
  • CURLINFO_HEADER_SIZE माध्यम से हेडर के आकार का पता लगाना हमेशा विश्वसनीय नहीं होता है, खासकर जब प्रॉक्सी का उपयोग किया जाता है या कुछ पुनर्निर्देशन परिदृश्यों में होता है।

सबसे सही विधि CURLOPT_HEADERFUNCTION का उपयोग कर CURLOPT_HEADERFUNCTION

यहां PHP बंद करने का उपयोग करके इसे करने का एक बहुत ही साफ तरीका है। यह सर्वर और HTTP संस्करणों में लगातार हैंडलिंग के लिए सभी शीर्षकों को लोअरकेस में परिवर्तित करता है।

यह संस्करण डुप्लिकेट हेडर बनाए रखेगा

यह आरएफसी 822 और आरएफसी 2616 का अनुपालन करता है, कृपया 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;

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

इसका एक समाधान 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);

चेतावनी: जैसा कि नीचे दी गई टिप्पणियों में उल्लेख किया गया है, यह प्रॉक्सी सर्वर के साथ या कुछ प्रकार के रीडायरेक्ट को संभालने पर विश्वसनीय होने पर विश्वसनीय नहीं हो सकता है। @ जेफ्री का जवाब इन अधिक भरोसेमंद तरीके से संभाल सकता है।


कर्ल के लिए विकल्प बनाया गया है, जिसे CURLOPT_HEADERFUNCTION कहा जाता है। इस विकल्प का मान कॉलबैक फ़ंक्शन का नाम होना चाहिए। कर्ल हेडर (और केवल हेडर!) को इस कॉलबैक फ़ंक्शन पर लाइन-बाय-लाइन पास करेगा (इसलिए हेडर सेक्शन के शीर्ष से शुरू होने वाले प्रत्येक हेडर लाइन के लिए फ़ंक्शन को कॉल किया जाएगा)। आपका कॉलबैक फ़ंक्शन इसके साथ कुछ भी कर सकता है (और दिए गए लाइन के बाइट्स की संख्या वापस करनी होगी)। यहां एक परीक्षण किया गया कोड है:

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

मेरा रास्ता है

$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];
}

यदि आवश्यक हो तो लूप के लिए आवेदन करें और विस्फोट सीमा को हटा दें।


यदि आप विशेष रूप से 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);

यहां कई उत्तरों के साथ समस्या यह है कि "\r\n\r\n" वैध रूप से एचटीएमएल के शरीर में दिखाई दे सकता है, इसलिए आप यह सुनिश्चित नहीं कर सकते कि आप हेडर सही तरीके से विभाजित कर रहे हैं।

ऐसा लगता है कि एक कॉल के साथ curl_exec अलग-अलग हेडर को स्टोर करने का एकमात्र तरीका है कॉलबैक का उपयोग करना जैसा कि ऊपर सुझाया गया है https://.com/a/25118032/3326494

और फिर (भरोसेमंद) अनुरोध के केवल शरीर को प्राप्त करने के लिए, आपको Content-Length शीर्षलेख के मान को substr() को ऋणात्मक प्रारंभ मान के रूप में पारित करने की आवश्यकता होगी।


सावधान रहें जब आपको सर्वर से लौटाई गई अंतिम सामग्री की आवश्यकता होती है। असली (अंतिम) शीर्षलेख और शरीर की प्रतीक्षा करते समय यह कोड आपकी अपेक्षा को तोड़ सकता है: 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;




curl