EisFuX: fsockopen()

Beitrag lesen

(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