fsockopen statt file_get_contents für HTTP-Requests

Bei zahlreichen Webspace-Providern ist die Funktionalität von file_get_contents für http deaktiviert. Es treten dann Fehlermeldungen wie

Warning: file_get_contents() [function.file-get-contents]: URL file-access is disabled in the server configuration in [..] und

Warning: file_get_contents([..]) [function.file-get-contents]: failed to open stream: no suitable wrapper could be found in [..]

auf. Mit folgender Funktion kann man das Verhalten von file_get_contents jedoch emulieren.

Die Funktion get_contents_by_uri benutzt fsockopen um Inhalte zu laden:

/**
 * Gets contents of any webside by an URI.
 * @author http://blog.root-of-all-evil.com
 * @param String $uri
 */
function get_contents_by_uri($uri) {
	$uriElem = parse_url ( $uri );
	$fp = @fsockopen ( $uriElem ['host'], 80, $errno, $errstr, 10 );

	if (! $fp) {
		throw new Exception ( "Could not create socket: '" . $errnstr . "' (" . $errno . ")." );
	}

	$request = "GET " . $uriElem ['path'] . (isset ( $uriElem ['query'] ) ? "?" . $uriElem ['query'] : "") . " HTTP/1.1\r\n";
	$request .= "Host: " . $uriElem ['host'] . "\r\n";
	$request .= "Connection: Close\r\n\r\n";

	fwrite ( $fp, $request );
	$response = "";
	while ( ! feof ( $fp ) ) {
		$response .= fgets ( $fp, 128 );
	}
	fclose ( $fp );

	// split headers from data
	$responseSplit = explode ( "\r\n\r\n", $response, 2 );

	return $responseSplit [1];
}

Erklärung

Socket erstellen

Die übergebene URI wird über die PHP-Funktion parse_url in ihre Teilmengen zerlegt. Anschließend wird ein Socket erstellt für den entsprechenden Host, auf Port 80 mit einem Timeout von 10 Sekunden. Fehlermeldungen unterdrücken wir durch das @, da wir explizit nach Erfolg abfragen und ggf. eine Ausnahme werfen.

Anfrage schicken, Antwort lesen

Danach wird über fwrite eine entsprechende GET-Anfrage geschickt, welche auch – falls vorhanden – die Parameter der URI und nicht nur den Pfad beachtet. Die darauffolgende Antwort wird in die Variable response gelesen.

Antwort bearbeiten und zurückgeben

Da diese neben dem eigentlichen Inhalt auch den Antwortheader enthält wird die Funktion explode benutzt um den Inhalt davon abzuschneiden. Durch den dritten Parameter bei explode mit dem Wert 2, stellen wir sicher, dass nur einmalig an Hand einer Leerzeile getrennt wird wie Sie sich zwischen Antwort-Header und HTML-Code befindet und nicht mehrmals, da natürlich auch Leerzeilen im HTML-Code selbst auftreten können.

Das zweite Element von responseSplit wird zurückgegeben, responseSplit[0] würde entsprechend den Antwort-Header liefern.

Beispielaufrufe

Der einfachste Aufruf:

echo get_contents_by_uri ( 'http://www.google.de/' );

Aufruf mit Parametern:

echo get_contents_by_uri ( 'http://www.google.de/search?hl=de&site=&q=test' );

Aufruf mit Ausnahmebehandlung:

try{
    echo get_contents_by_uri ( 'http://does_not_exist_.com/bogus.html' );
}
catch(Exception $e)
{
    echo "get_contents_by_uri: ".$e->getMessage();
}

Weitere Links:

Share

Leave a Comment