Kann PHP cURL Antwort-Header UND -Text in einer einzigen Anfrage abrufen?

Lesezeit: 9 Minuten

Kann PHP cURL Antwort Header UND Text in einer einzigen Anfrage
Gremo

Gibt es eine Möglichkeit, Header und Body für eine cURL-Anfrage mit PHP zu erhalten? Ich habe diese Option gefunden:

curl_setopt($ch, CURLOPT_HEADER, true);

wird die zurückgeben Körper plus Kopfzeilen, aber dann muss ich es analysieren, um den Körper zu bekommen. Gibt es eine Möglichkeit, beides auf benutzerfreundlichere (und sicherere) Weise zu erhalten?

Beachten Sie, dass ich mit “einzelner Anfrage” die Vermeidung einer HEAD-Anfrage vor GET/POST meine.

  • Dafür gibt es eine integrierte Lösung, siehe diese Antwort: stackoverflow.com/a/25118032/1334485 (diesen Kommentar hinzugefügt, weil dieser Beitrag immer noch viele Aufrufe erhält)

    – Skac

    16. April 2015 um 21:59 Uhr


  • Schau dir diesen netten Kommentar an: secure.php.net/manual/en/book.curl.php#117138

    – Benutzer956584

    24. August 2015 um 10:35 Uhr

  • a-curl_multi-working-example—das-tatsächlich-funktioniert

    Benutzer257319

    2. Dezember 2015 um 1:52 Uhr


  • Mir wurde gesagt, meine Frage sei ein Duplikat dieser Frage. Wenn es kein Duplikat ist, kann es bitte jemand erneut öffnen? stackoverflow.com/questions/43770246/… In meiner Frage habe ich eine konkrete Anforderung, eine Methode zu verwenden, die ein Objekt mit getrennten Kopf- und Körperteilen und nicht mit einer Zeichenfolge zurückgibt.

    – 1,21 Gigawatt

    4. Mai 2017 um 4:00 Uhr


1646966049 597 Kann PHP cURL Antwort Header UND Text in einer einzigen Anfrage
iblau

Eine Lösung hierfür wurde in den Kommentaren der PHP-Dokumentation veröffentlicht: http://www.php.net/manual/en/function.curl-exec.php#80442

Codebeispiel:

$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 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);

Warnung: Wie in den Kommentaren unten angemerkt, ist dies möglicherweise nicht zuverlässig, wenn es mit Proxy-Servern verwendet wird oder wenn bestimmte Arten von Weiterleitungen verarbeitet werden. Die Antwort von @Geoffrey kann diese zuverlässiger handhaben.

  • Du kannst auch list($header, $body) = explode("\r\n\r\n", $response, 2)aber je nach Größe Ihrer Anfrage kann dies etwas länger dauern.

    – iblau

    7. Februar 2012 um 21:33 Uhr

  • Dies ist eine schlechte Lösung, denn wenn Sie einen Proxy-Server verwenden und Ihr Proxy-Server (z. B. Fiddler) eigene Header zur Antwort hinzufügt – diese Header haben alle Offsets zerstört und sollten verwendet werden list($header, $body) = explode("\r\n\r\n", $response, 2) als einzige funktionierende Variante

    – msangel

    25. Februar 2013 um 2:17 Uhr

  • @msangel Ihre Lösung funktioniert nicht, wenn die Antwort mehrere Header enthält, z. B. wenn der Server eine 302-Umleitung durchführt. Irgendwelche Vorschläge?

    – Nate

    8. April 2014 um 0:32 Uhr

  • @Nate, ja, das weiß ich. AFAIK, aber es gibt nur einen möglichen zusätzlichen Header – mit Code 100 (Fortsetzen). Für diesen Header können Sie mit der korrekten Definition der Anforderungsoption umgehen: curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); , wodurch das Senden dieser Header-Antwort deaktiviert wird. Wie für 302sollte dies nicht passieren, da der 302-Header umgeleitet wird und keinen Körper erwartet, aber ich weiß, manchmal senden Server einen Körper mit 302 Antwort, aber es wird sowieso von Browsern ignoriert, warum sollte Curl damit umgehen?)

    – msangel

    8. April 2014 um 14:37 Uhr


  • CURLOPT_VERBOSE ist dazu bestimmt, Prozessinformationen auszugeben STDERR (kann in CLI stören) und für das besprochene Problem ist es nutzlos.

    – hejdav

    8. April 2015 um 15:46 Uhr

Kann PHP cURL Antwort Header UND Text in einer einzigen Anfrage
Geoffrey

Viele der anderen Lösungen, die dieser Thread anbietet, sind nicht das richtig machen.

  • Aufteilen \r\n\r\n ist nicht zuverlässig, wann CURLOPT_FOLLOWLOCATION eingeschaltet ist oder wenn der Server mit einem 100-Code antwortet.
  • Nicht alle Server sind standardkonform und übertragen nur a \n für neue Linien.
  • Ermitteln der Größe der Header über CURLINFO_HEADER_SIZE ist auch nicht immer zuverlässig, insbesondere wenn Proxys verwendet werden oder in einigen der gleichen Umleitungsszenarien.

Die richtigste Methode ist die Verwendung CURLOPT_HEADERFUNCTION.

Hier ist eine sehr saubere Methode, dies mit PHP-Closures durchzuführen. Es wandelt auch alle Header in Kleinbuchstaben um, um eine konsistente Handhabung über Server und HTTP-Versionen hinweg zu gewährleisten.

Diese Version behält doppelte Kopfzeilen bei

Dies entspricht RFC822 und RFC2616, bitte schlagen Sie keine Änderungen vor, um die zu verwenden mb_ String-Funktionen, es ist falsch!

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

  • IMO ist dies die beste Antwort in diesem Thread und behebt Probleme mit Umleitungen, die bei anderen Antworten aufgetreten sind. Lesen Sie dazu am besten die Dokumentation CURLOPT_HEADERFUNKTION um zu verstehen, wie es funktioniert und mögliche Fallstricke. Ich habe auch einige Verbesserungen an der Antwort vorgenommen, um anderen zu helfen.

    – Simon Osten

    9. Juni 2017 um 7:06 Uhr


  • Großartig, ich habe die Antwort aktualisiert, um doppelte Header zu berücksichtigen. Formatieren Sie den Code in Zukunft nicht mehr so, wie Sie es für richtig halten. Dies ist so geschrieben, dass deutlich wird, wo die Grenzen der Abschlussfunktion liegen.

    – Geoffrey

    9. Juni 2017 um 7:20 Uhr

  • @thealexbaron Ja, es ist ab PHP 5.4, siehe: php.net/manual/en/migration54.new-features.php

    – Geoffrey

    18. Juli 2017 um 0:39 Uhr

  • Diese Antwort wird für einen so ordentlichen und RFC-konformen Ansatz stark unterschätzt. Dies sollte eine klebrige Antwort sein und nach oben verschoben werden. Ich wünschte nur, es gäbe einen schnelleren Ansatz, um den Wert eines gewünschten Headers zu erhalten, anstatt zuerst alle Header zu analysieren.

    – Fr0zenFyr

    17. Mai 2018 um 9:01 Uhr


  • @Mahesh.D nein, $data = curl_exec($ch); gibt den Inhalt zurück, wenn CURLOPT_RETURNTRANSFER wird gemäß dem bereitgestellten Beispiel eingestellt.

    – Geoffrey

    26. Juni 2019 um 11:26 Uhr

1646966050 178 Kann PHP cURL Antwort Header UND Text in einer einzigen Anfrage
Skacc

Curl hat dafür eine eingebaute Option namens CURLOPT_HEADERFUNCTION. Der Wert dieser Option muss der Name einer Callback-Funktion sein. Curl übergibt den Header (und nur den Header!) Zeile für Zeile an diese Callback-Funktion (also wird die Funktion für jede Header-Zeile aufgerufen, beginnend am Anfang des Header-Abschnitts). Ihre Callback-Funktion kann dann alles damit machen (und muss die Anzahl der Bytes der angegebenen Zeile zurückgeben). Hier ist ein getesteter Arbeitscode:

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

Das Obige funktioniert mit allem, auch mit verschiedenen Protokollen und Proxys, und Sie müssen sich keine Gedanken über die Header-Größe machen oder viele verschiedene Curl-Optionen festlegen.

PS: Um die Kopfzeilen mit einer Objektmethode zu behandeln, tun Sie dies:

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

  • Als Hinweis wird die Callback-Funktion für jeden Header aufgerufen und es scheint, dass sie nicht getrimmt sind. Sie können eine globale Variable verwenden, um alle Header zu speichern, oder Sie können eine anonyme Funktion für den Rückruf verwenden und eine lokale Variable verwenden (lokal für den übergeordneten Bereich, nicht die anonyme Funktion).

    – MV.

    25. April 2015 um 23:55 Uhr

  • @MV Danke, ja, mit “Zeile für Zeile” meinte ich “jeden Header”. Ich habe meine Antwort aus Gründen der Übersichtlichkeit bearbeitet. Um den gesamten Kopfzeilenabschnitt (auch bekannt als alle Kopfzeilen) zu erhalten, können Sie auch eine Objektmethode für den Rückruf verwenden, damit eine Objekteigenschaft alle enthalten kann.

    – Skac

    26. April 2015 um 12:06 Uhr

  • Dies ist die beste Antwort IMO. Es verursacht keine Probleme mit mehreren “\r\n\r\n”, wenn CURLOPT_FOLLOWLOCATION verwendet wird, und ich denke, es wird nicht durch zusätzliche Header von Proxys beeinflusst.

    – Rafal G.

    2. Juli 2015 um 11:43 Uhr

  • Hat bei mir sehr gut funktioniert, siehe auch stackoverflow.com/questions/6482068/… bei Problemen

    – RH

    4. April 2016 um 15:12 Uhr

  • Ja, dies ist der beste Ansatz, aber die Antwort von @Geoffrey macht dies sauberer, indem eine anonyme Funktion verwendet wird, ohne dass globale Variablen und dergleichen erforderlich sind.

    – Simon Osten

    9. Juni 2017 um 6:50 Uhr

1646966050 884 Kann PHP cURL Antwort Header UND Text in einer einzigen Anfrage
Benutzer1031143

ist es das, wonach du suchst?

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

Wenn Sie dies ausdrücklich wünschen Content-Typegibt es eine spezielle cURL-Option, um sie abzurufen:

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

  • Das OP hat gefragt, ob es eine Möglichkeit gibt, die Header abzurufen, nicht einen bestimmten Header. Dies beantwortet die Frage des OP nicht.

    – Geoffrey

    6. Juni 2019 um 2:38 Uhr

1646966051 443 Kann PHP cURL Antwort Header UND Text in einer einzigen Anfrage
Kyrill H.

Legen Sie einfach Optionen fest:

  • CURLOPT_HEADER, 0

  • CURLOPT_RETURNTRANSFER, 1

und verwenden Sie curl_getinfo mit CURLINFO_HTTP_CODE (oder kein Opt-Parameter und Sie haben ein assoziatives Array mit allen gewünschten Informationen)

Mehr bei : http://php.net/manual/fr/function.curl-getinfo.php

  • Das OP hat gefragt, ob es eine Möglichkeit gibt, die Header abzurufen, nicht einen bestimmten Header. Dies beantwortet die Frage des OP nicht.

    – Geoffrey

    6. Juni 2019 um 2:38 Uhr

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

Arbeitet mit HTTP/1.1 100 Continue vor anderen Überschriften.

Wenn Sie mit fehlerhaften Servern arbeiten müssen, die nur LF anstelle von CRLF als Zeilenumbrüche senden, können Sie verwenden preg_split wie folgt:

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

  • Sollte nicht $parts = explode("\r\n\r\nHTTP/", $response); haben 3. Parameter für explodieren als 2?

    – Benutzer4271704

    21. August 2015 um 19:16 Uhr

  • @ user4271704 Nein. Es erlaubt, die letzte HTTP-Nachricht zu finden. HTTP/1.1 100 Continue kann mehrfach vorkommen.

    – Enyby

    22. August 2015 um 9:25 Uhr

  • Aber er sagt etwas anderes: stackoverflow.com/questions/9183178/… wer von euch hat recht?

    – Benutzer4271704

    24. August 2015 um 9:20 Uhr

  • HTTP/1.1 100 Continue kann mehrfach vorkommen. Er sieht den Fall an, wenn er nur einmal erscheint, aber im Normalfall falsch ist. Zum Beispiel für HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK...\r\n\r\n... Sein Code funktioniert nicht richtig

    – Enyby

    24. August 2015 um 9:35 Uhr

  • Das Aufteilen auf \r\n ist nicht zuverlässig, einige Server entsprechen nicht den HTTP-Spezifikationen und senden nur ein \n. Der RFC-Standard besagt, dass Anwendungen \r ignorieren und für größtmögliche Zuverlässigkeit auf \n aufteilen sollten.

    – Geoffrey

    9. Juni 2017 um 7:24 Uhr

989630cookie-checkKann PHP cURL Antwort-Header UND -Text in einer einzigen Anfrage abrufen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy