Curl-Fehler 18 - Übertragung geschlossen, ausstehende Lesedaten verbleiben


70

Wenn ich Daten von einer URL mit Curl abrufe, bekomme ich manchmal (in 80% der Fälle)

Fehler 18: Übertragung geschlossen mit verbleibenden ausstehenden Lesedaten

Ein Teil der zurückgegebenen Daten fehlt dann. Das Seltsame ist, dass dies niemals auftritt, wenn CURLOPT_RETURNTRANSFER auf false gesetzt ist, dh die Funktion curl_exec gibt die Daten nicht zurück, sondern zeigt den Inhalt direkt an.

Was könnte das Problem sein? Kann ich einige Optionen festlegen, um ein solches Verhalten zu vermeiden?


Können Sie uns die URL geben, die Sie versuchen? Es könnte eine schlechte Verbindung sein, wenn Sie dies auf Ihrem lokalen Host testen.
Fragezeichen

1
Senden Sie Connection: CloseHeader? Wenn ja, versuchen Sie es mit so etwas wie Connection: Keep-Aliveund Keep-Alive: ***wo *** eine Zahl Ihrer Wahl ist, die Sinn macht (vielleicht 10 Sekunden, um sicher zu gehen; die meisten modernen Browser verwenden 300, was 5 Minuten entspricht).
Veröffentlicht

Antworten:


35

Ich wette, dies hängt mit einem falschen Content-LengthHeader zusammen, der vom Peer gesendet wurde. Mein Rat ist, Curl die Länge selbst einstellen zu lassen.


5
Dies kann mit dem Content-Length-Antwortheader zusammenhängen. Ich habe einen ähnlichen Fall in einem der Mitarbeiterprojekte festgestellt: Ein Java-Webservice-Gateway legt die
Inhaltslänge auf

Ich glaube, @pcdinh ist richtig. Wir haben das gleiche mit einer nicht abgeschlossenen Chunked-Transfer-Codierung. curl erwartet mehr Daten (der Server hat angekündigt, mehr zu senden oder sendet nicht die abschließende 0), aber der Server schließt die Verbindung.
iGEL

2
Es ist keine "Inhaltslänge" enthalten, Beispiel beigefügt.
MariuszS

1
Wie habt ihr es geschafft, das zu beheben? Ich sende keine Inhaltslänge im Code. Wird etwas automatisch von der Serverseite hinzugefügt?
Mijoe

46

Die Fehlerzeichenfolge ist ganz einfach genau das, was libcurl sieht: Da es einen Chunk-Codierungsstrom empfängt, weiß es, wann in einem Chunk noch Daten zu empfangen sind. Wenn die Verbindung geschlossen wird, weiß libcurl, dass der zuletzt empfangene Block unvollständig war. Dann erhalten Sie diesen Fehlercode.

Sie können nichts tun, um diesen Fehler bei unveränderter Anforderung zu vermeiden. Sie können jedoch versuchen, ihn zu umgehen , indem Sie stattdessen eine HTTP 1.0-Anforderung ausgeben (da dann keine Chunked-Codierung erfolgt). Fakt ist jedoch, dass dies höchstwahrscheinlich ein Fehler ist auf dem Server oder in Ihrem Netzwerk / Setup irgendwie.


1
Für mich war das Problem auf einem entfernten Ende, über das ich keine Kontrolle hatte, und die einzige funktionierende Lösung bestand darin, 1.0 damit zu erzwingen: curl_setopt ($ curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Eric Caron

@ DanielStenberg immer noch das gleiche Problem.

Einstellen von HTTP ver. 1.0 half mir mit Chunked Encoing und seltsamen Hex-Markierungen in abgerufenen Daten. Vielen Dank für diesen Hinweis!
Givi

Passiert das für eine bestimmte URL, für die wir Curl verwenden? @ EricCaron
Mona Jalal

@MonaJalal Ich habe den Remote-Server nicht ausgeführt, daher ist mir seine Konfiguration nicht bekannt. Ich vermutete, dass IIS unterschiedliche Konfigurationen hatte und unterschiedlich auf 1.0- und 1.1-Anfragen reagierte.
Eric Caron

7

Ich hatte das gleiche Problem, konnte es jedoch beheben, indem ich den Header 'Expect: 100-continue' unterdrückte, den cURL normalerweise sendet (das Folgende ist PHP-Code, sollte aber ähnlich mit anderen cURL-APIs funktionieren):

curl_setopt($curl, CURLOPT_HTTPHEADER, array('Expect:'));

Übrigens sende ich Anrufe an den HTTP-Server, der im JDK 6-REST-Material enthalten ist und Probleme aller Art aufweist. In diesem Fall wird zuerst eine 100-Antwort gesendet, und bei einigen Anforderungen wird die nachfolgende 200-Antwort nicht korrekt gesendet.


Wo würden wir diese Einstellung ändern? Ich weiß nur nicht, wo ich diese Zeile hinzufügen soll, wenn cURL in Windows ist.
DomainsFeatured

1
@DomainsFeatured Ich bin mir nicht sicher, was Sie unter "cURL ist in Windows" verstehen, aber in der Befehlszeile können Sie den Header 'Expect:' unterdrücken, indem Sie ihm einen leeren Wert geben: curl -H 'Expect:' ...Ich hoffe, dies hilft ...
jcsahnwaldt Reinstate Monica

Ich verwende WordPress auf IIS und es verwendet cURL, daher weiß ich nicht, wo ich diese Option angeben soll: - /
DomainsFeatured

Ich weiß nicht viel über WordPress, aber es ist Open Source, daher sollten Sie in der Lage sein, den relevanten Teil des PHP-Codes zu finden und im Grunde nur die Zeile aus meiner Antwort einzufügen (wahrscheinlich nachdem $curlSie den Namen in den Namen geändert haben, der darin heißt Code).
jcsahnwaldt Reinstate Monica

Ich bin ein wenig verwirrt. Der Header "Expect : 100" wird für den Server verwendet, um den Client zum Senden von Daten zu ermutigen, nicht jedoch für den Client zum Empfangen von Daten. Wie kann die Unterdrückung dieses Headers dem Client helfen, Daten zu empfangen? Vielen Dank.
Joey Sun

6

Diesen Fehler auch während der Verwendung von Guzzle sehen. Der folgende Header hat es für mich behoben:

'headers' => [
    'accept-encoding' => 'gzip, deflate',
],

Ich habe die Anfrage an Postman gesendet, die mir eine vollständige Antwort und keinen Fehler gab. Dann fing ich an, die Header hinzuzufügen, die Postman an die Guzzle-Anfrage sendet, und dies war derjenige, der das Problem behoben hat.


Danke, das hat bei mir funktioniert. Ich habe mit dem Postboten versucht, Antwortheader abzurufen, und festgestellt, dass die Antwort gzip zurückgibt, also habe ich dies hinzugefügt.
Parminder Singh

3

Ich habe diesen Fehler erhalten, als mein Serverprozess während der Generierung der Antwort eine Ausnahme bekam und einfach die Verbindung schloss, ohne sich zu verabschieden. Curl erwartete noch Daten von der Verbindung und beschwerte sich (zu Recht).


2

Ich hatte dieses Problem mit Pycurl und habe es mit gelöst

c.setopt(pycurl.HTTP_VERSION, pycurl.CURL_HTTP_VERSION_1_0) 

wie Eric Caron sagt.


1

Ich habe diesen Fehler auf diese Weise behoben.

$ch = curl_init ();
curl_setopt ( $ch, CURLOPT_URL, 'http://www.someurl/' );
curl_setopt ( $ch, CURLOPT_TIMEOUT, 30);
ob_start();
$response = curl_exec ( $ch );
$data = ob_get_clean();
if(curl_getinfo($ch, CURLINFO_HTTP_CODE) == 200 ) success;

Es tritt immer noch ein Fehler auf, aber ich kann Antwortdaten in Variablen verarbeiten.


1

Ich habe diesen Fehler erhalten, als ich versehentlich eine Datei auf sich selbst heruntergeladen habe.
(Ich hatte einen Symlink in einem sshfs-Mount des Remote-Verzeichnisses erstellt, um ihn zum Download zur Verfügung zu stellen, vergaß, das Arbeitsverzeichnis zu wechseln, und verwendete -OJ).

Ich denke, es wird Ihnen beim Lesen nicht wirklich »helfen«, da dies bedeutet, dass Ihre Datei in den Papierkorb verschoben wurde.


1

Bei einem ähnlichen Problem ist mein Server hinter nginx. Es gibt keinen Fehler im Protokoll des Webservers (Python Flask), aber einige Fehlermeldungen im Nginx-Protokoll.

[krit] 31054 # 31054: * 269464 open () "/ var / cache / nginx / proxy_temp / 3/45/0000000453" ist beim Lesen des Upstreams fehlgeschlagen (13: Berechtigung verweigert)

Ich habe dieses Problem behoben, indem ich die Berechtigung des Verzeichnisses korrigiert habe:

/var/cache/nginx
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.