Kann PHP cURL Antwort-Header UND -Text in einer einzigen Anfrage abrufen?
Lesezeit: 9 Minuten
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)
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.
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
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.
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.
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
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:
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:
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.
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
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)
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
9896300cookie-checkKann PHP cURL Antwort-Header UND -Text in einer einzigen Anfrage abrufen?yes
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