HTTP Problem bei Verwendung von fsockopen
Sven
- php
0 Ork am Pork1 Der Martin
0 Sven
0 fsockopen()
EisFuX
Hallo ihr,
ich hab mit fsockopen() eine Verbindung zu einem HTTP-Server geöffnet und sende mehrere Requests. Das Problem dabei ist, dass ich einen 400-Error (Bad Request) erhalte. Ich denke, das Problem besteht dabei, die Verbindung wieder zu beenden... das macht man offenbar mit einem doppelten \r\n\r\n.
Dafür hab ich am Ende jeder Zeile \r\n stehen und ganz unten drunter als letztes nochmal \r\n.
Hier mal der Code:
$fp = fsockopen($host, 80);
fputs($fp, "POST / HTTP/1.1\r\n");
fputs($fp, "Host: www.example.com\r\n");
fputs($fp, "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; bgft)\r\n");
fputs($fp, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n");
fputs($fp, "Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3\r\n");
fputs($fp, "Accept-Encoding: gzip,deflate\r\n");
fputs($fp, "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n");
fputs($fp, "Connection: close\r\n");
fputs($fp, "Referer: $referer\r\n");
fputs($fp, "Cookie: ".$cookie."\r\n");
fputs($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-Length: 24\r\n");
fputs($fp, "login=user&pass=password\r\n");
fputs($fp, "\r\n");
Und diese Fehlermeldung erhalte ich:
Your browser sent a request that this server could not understand.
Request header field is missing ':' separator.
login=user&pass=password
Wenn ich das letzte \r\n weglasse und direkt hinter Connect: close\r\n hänge, dann gehts. Aber dann wird natürlich alles ignoriert, was darunter noch kommt... das ist schlecht.
Weiß jemand, wo das Problem liegt?
Grüße
Sven
Hallo,
Weiß jemand, wo das Problem liegt?
hast du doch schon selbst geschrieben, ich reduziere das mal auf's Wesentliche:
Request header field is missing ':' separator.
login=user&pass=password
Dann schaust du mal in deinen Code und findest dort folgende zwei Zeilen:
fputs($fp, "Content-Length: 24\r\n");
fputs($fp, "login=user&pass=password\r\n");
Die zweite ist offensichtlich die bemängelte. Fällt dir im Vergleich mit der ersten was auf?
Hallo,
ich hab mit fsockopen() eine Verbindung zu einem HTTP-Server geöffnet und sende mehrere Requests. Das Problem dabei ist, dass ich einen 400-Error (Bad Request) erhalte. Ich denke, das Problem besteht dabei, die Verbindung wieder zu beenden... das macht man offenbar mit einem doppelten \r\n\r\n.
nein, das hast du wohl missverstanden. Mit dem doppelten Zeilenumbruch wird nur der Request-Header beendet und damit quasi vom Request-Body (falls vorhanden) getrennt.
fputs($fp, "Content-Length: 24\r\n");
fputs($fp, "login=user&pass=password\r\n");
Zwischen diesen beiden Zeilen sollte der doppelte Umbruch stehen. Denn die letzte Zeile sendet ja schon die eigentlichen POST-Daten, also den Inhalt (Body) des Requests.
Your browser sent a request that this server could not understand.
Request header field is missing ':' separator.
Zu Recht.
login=user&pass=password
Der Server versucht verzweifelt, diese Zeile noch als HTTP-Header zu interpretieren, und scheitert schon allein an der Formalität, dass nach dem vermeintlichen Keyword kein ':' kommt.
Weiß jemand, wo das Problem liegt?
Die HTTP-Spezifikation?
So long,
Martin
Hallo,
fputs($fp, "Content-Length: 24\r\n");
fputs($fp, "login=user&pass=password\r\n");Zwischen diesen beiden Zeilen sollte der doppelte Umbruch stehen. Denn die letzte Zeile sendet ja schon die eigentlichen POST-Daten, also den Inhalt (Body) des Requests.
Ahhh vielen Dank! Ja, das hatte ich falsch verstanden... \r\n\r\n beendet den HTTP-Header, nicht den ganzen Request - jetzt klappts! :D
Grüße
Sven
(Hallo|Hi(ho)|Mahlzeit) Sven,
ich hab mit fsockopen() eine Verbindung zu einem HTTP-Server geöffnet und sende mehrere Requests. Das Problem dabei ist, dass ich einen 400-Error (Bad Request) erhalte. Ich denke, das Problem besteht dabei, die Verbindung wieder zu beenden... das macht man offenbar mit einem doppelten \r\n\r\n.
Nein, damit beendet man den HTTP-Header.
Hier mal der Code:
$fp = fsockopen($host, 80);
fputs($fp, "POST / HTTP/1.1\r\n");
...
fputs($fp, "Content-Length: 24\r\n");
fputs($fp, "login=user&pass=password\r\n");
fputs($fp, "\r\n");
So rum würde ein Schuh draus:
~~~php
$fp = fsockopen($host, 80);
fputs($fp, "POST / HTTP/1.1\r\n");
...
fputs($fp, "Content-Length: 24\r\n");
fputs($fp, "\r\n");
// jetzt ist der Header "beendet"
// und jetzt commt der "content":
fputs($fp, "login=user&pass=password\r\n");
Nach dem du dem Server deine Anfrage geschickt hast, kommt das Empfangen der Antwort. Hier gibt es mehrere Fallstricke:
1. fread($socket, $length) liest nicht immer so viele Bytes ein, wie mit dem Parameter $length angegeben wurden. Du musst also den Rückgabewert von fread() mit der ursprünglich "angeforderten" Byte-Zahl vergleichen und eventuell fehlende Bytes "nachholen".
2. Dein Client gibt sich als HTTP/1.1-fähig aus und sendet spezielle Header, also muss er auch Daten in Einzelteilen ("Transfer-Encoding: Chunked") und in komprimierter Form (bspw. "Content-Encoding: gzip") empfangen können. Ob der Webserver die Daten derart versendet, erfährst du über die Response-Header.
Die Verbindung wird komplett beendet (getrennt), wenn du fclose() benutzt.
Die Handbuchseite zu fsockopen() hat ein paar nette Anwendungsbeispiele in den "user contributed notes".
Es ist auch hilfreich, sich anzuschauen, welche Header ein richtiger HTTP-Client (sprich: "Browser") so mit einem Web-Server austauscht. Da kann man sich viel von abkucken. Google doch mal nach LiveHTTPHeaders, TamperData, BurpProxy, Fiddler usw.
MffG
EisFuX