PHP Maniac

Das PHP Blog für PHP-Profis und alle die es werden wollen

HTTP GET Requests mit PHP erzeugen

27 April, 2009 (18:22) | Code-Schnipsel, PHP, Server | Von: PHP Maniac

Wer sich mit PHP gerne mal einen kleinen Crawler oder Proxy programmieren möchte, ist sicher schon über die Erzeugung von HTTP Requests gestolpert. Zwar bietet PHP mit der Funktion file_get_contents() bei entsprechend konfiguriertem Webspace eine einfache Möglichkeit Webseiten auf anderen Servern abzurufen, allerdings lässt diese keine Einstellungen wie z.B. den User-Agent zu. Wer also mehr erwartet als das bloße Abrufen von Webseiten, oder wenn die Webseite den PHP User-Agent blockt, muss selbst Hand anlegen. Wie das geht, werde ich im folgenden kurz Beschreiben.

Das HTTP Protokoll

Zunächst einige kurze Informationen über das HTTP Protokoll, welche für das Verständnis des Codes sehr nützlich sind. Das HTTP Protokoll beschreibt mehrere verschiedene Anfragetypen, die beiden bekanntesten hierbei sind sicherlich GET und POST. In diesem Beitrag möchte ich mich vorest auf den HTTP Get Request beschränken.

Ein HTTP GET Request fordert bestimmte Inhalte vom Server an. Zunächst wird eine einfache TCP/IP Verbindung mit dem Server hergestellt, in 99% der Fälle wird hierbei der HTTP Standard Port verwendet (Port 80). Lediglich HTTPS und einige exotisch konfigurierte Server bieten ihre Webseiten auf anderen Ports an.

Wurde die Verbindung hergestellt, so erwartet der Webserver eine HTTP konforme Anfrage, die beim HTTP GET Request wie folgt aussieht:

GET /index.php?q=test HTTP/1.1
HOST: www.google.de
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.12) Gecko/20050919 Firefox/1.0.7
Connection: Close

Wichtig hierbei ist, dass die Zeilenumbrüche nicht nur aus einem Newline (\n) bestehen dürfen, sondern aus Carriage Return und Newline bestehen müssen (\r\n). Abgeschlossen wird der HTTP GET Request mit einem doppelten Zeilenumbruch (\r\n\r\n).

HTTP GET Requests im Detail

Nun schauen wir und die Anfrage einmal etwas genauer an, hierbei beginnen wir mit der ersten Zeile:

GET /index.php?q=test HTTP/1.1

Zunächst wird hier die Art der Anfrage definiert, in diesem Falle natürlich GET. Nach einem Leerzeichen wird die gewünschte Datei mit ihren Parametern definiert. Hierbei ist darauf zu achten, dass wirklich nur Dateiname und Parameter angegeben werden und nicht auch die Domain oder ähnliches. Durch ein weiteres Leerzeichen getrennt folgt nun noch das verwendete Protokoll, hier HTTP in Version 1.1.

HOST: www.google.de

In der Zweiten Zeile wird dann der angesprochene Host übergeben. Dies ist notwendig, da viele Server für eine Vielzahl von verschiedenen Domains zuständig sind. Damit diese die angefragte Datei richtig zuordnen können, muss mit dem HOST Befehl die gewünschte Domain festgelegt werden.

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.12) Gecko/20050919 Firefox/1.0.7

Mit Hilfe des User-Agent Befehls, wird dem Server dann mitgeteilt, welcher Browsertyp in welcher Version für die Anfrage verwendet wird. Hier im Beispiel handelt es sich um eine, mittlerweile, sehr alte Version von Firefox (Version 1.0.7). Neben Browser und Version wird weiterhin das verwendete Betriebssystem übergeben. Wenn wir den HTTP GET Request mit PHP nachbilden, können als User-Agent beliebige Browser simuliert werden. Dies empfiehlt sich gerade für das Parsen von Webseiten, die eventuell nicht geparsed werden möchten, diese können die Anfrage dann nur schwer von den Anfragen normaler Besucher unterscheiden. Es können jedoch auch bewusst eigene User-Agents erfunden und verwendet werden.

Connection: Close

Abschließend teilen wir dem Server noch mit, dass die Verbindung nach der Abfrage geschlossen werden soll. Es ist auch möglich die Verbindung für weitere Abfragen aufrecht zu erhalten, jedoch würde dies den Rahmen dieses Beitrags sprengen.

HTTP GET in PHP

Nun wollen wir die obigen Erkenntnisse in einem kleinen PHP Programm umsetzen. Hierzu wird zunächst mit fsockopen() eine Verbindung mit dem Server hergestellt. Ist der Verbindungsaufbau erfolgreich, so senden wir unseren HTTP GET Request und empfangen danach die vom Server gelieferten Daten.

$host = "www.google.de";
$port = 80;
$url = "/index.php?q=test";
 
$timeout = 30;
 
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
if($fp)
{
	$request = "GET ".$url." HTTP/1.1\r\n";
	$request.= "Host: ".$host."\r\n";
	$request.= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.12) Gecko/20050919 Firefox/1.0.7\r\n";
	$request.= "Connection: Close\r\n\r\n";
 
	fwrite($fp, $request);
	while (!feof($fp))
	{
		$data .= fgets($fp, 128);
	}
	fclose($fp);
	echo $data;
}
else
{
	echo "ERROR: ".$errstr;
}

Klappt die Anfrage, so wird der Server ebenfalls mit einem HTTP Header antworten, der umgefähr so aussehen wird:

HTTP/1.0 200 OK
Date: Fri, 19 Jan 2008 12:15:45 GMT
Last-Modified: Tue, 11 Jan 2007 15:19:30 GMT
Content-Language: de
Content-Type: text/html; charset=utf-8

Nach dem Header folgt dann der eigentliche Inhalt der angeforderten Webseite. Die Daten sind vom Header durch einen doppelten Zeilenumbruch (\r\n\r\n) getrennt. Somit lassen sich die beiden Bereiche durch ein explode() trennen:

list($header, $html) = explode("\r\n\r\n", $data);

Selbstverständlich ist der vorgestellte Code (noch) nicht perfekt, vielmehr ist er als eine Basis für eigene Entwicklungen gedacht. Denkbar wäre z.B. eine Erkennung der HTTP Statuscodes, die der Server in seiner Antwort sendet (im Beispiel 200 für OK). In den nächsten Tagen werde ich dann noch einen Artikel für die etwas komplexeren HTTP POST Requests veröffentlichen.

Soviel zum HTTP GET Request, Kommentare und eigene Experimente sind gern gesehen. Wie immer sind der Fantasie keine Grenzen gesetzt…

Be Sociable, Share!

Kommentare

Pingback von HTTP Header mit PHP verändern – PHP Maniac – Das PHP Blog
Datum 11. Mai 2009 um 09:09 Uhr

[…] wir bereits beim Erstellen von HTTP GET Requests mit PHP gesehen haben, sieht das HTTP Protokoll verschiedene Header-Informationen vor, die die […]

Pingback von Twitter mit PHP fernsteuern – Die Twitter-API machts möglich » Twitter-API, Twitter, cURL, Serie, Funktion, Daten » PHP Maniac
Datum 19. Februar 2010 um 22:27 Uhr

[…] ist. Selbstverständlich wäre es auch möglich die bereits an anderer Stelle präsentierten HTTP-GET Requests dafür zu verwenden. Da sämtliche Interaktion mit der Twitter-API über solche Anfragen […]

Pingback von Mailen mit PHP – Über das automatisierte Versenden von Emails » Funktion, Emails, Header, Email, Dies, Nachricht » PHP Maniac
Datum 19. Februar 2010 um 23:09 Uhr

[…] einen doppelten Zeilenumbruch mit „rn“ abgeschlossen werden, wie wir es schon von unseren Headern bei den http Requests gelernt haben. Klickt der Empfänger jetzt auf Antworten um auf unser Email zu antworten, so wird […]

Kommentar von syntax
Datum 10. März 2012 um 00:16 Uhr

Ich warte schon seit Jahren auf die Fortsetzung…

Kommentar von PHP Maniac
Datum 14. März 2012 um 21:29 Uhr

Leider hatte ich die letzten Monate extrem wenig Zeit, eine Wiederaufnahme des Blogs und damit auch die Fortsetzung ist aber weiter fest geplant. Einen verbindlichen Termin kann ich dir leider aber noch nicht nennen…

Kommentar von investmentclub
Datum 24. Juni 2013 um 09:56 Uhr

Einbettungen (z.B Bilder) sind leider nicht zu sehen

Siehe http:investmentclub-hanau.de/a4.php

Kommentar von piwwo
Datum 3. Januar 2014 um 13:26 Uhr

Btw. „GET „.$url.“ HTTP/1.1\r\n“; ist schlechter Stil. Entweder man nutzt durchgehend einfache Anführungszeichen ‚ und setzt mit . zusammen, oder man schreibt die Variable in „-Strings, ohne . da „-Stings sowieso schon interpretiert werden (und für \r\n auch müssen).

Schreibe einen Kommentar