| Wenn ihr Browser eine Webseite anfordert, dann sendet der entsprechende Webserver vor dem HTML-Quelltext der Seite einige Zeilen Text - den HTTP Response-Header. | Moderne Programmiersprachen bieten die Möglichkeit, den HTTP-Header empfangener Seiten zu analysieren (wie hier), bzw. den Header gesendeter Seiten nach Bedarf zu gestalten. |
Internet |
Protokolle, Dienste und Services - HTTP |
| HTTP | Grundlagen und Übersicht |
| Live-Header | Live-Analyse der Header beliebiger Webseiten |
| HTTP-Felder | Informationen vom Webserver an den Browser |
| Perl | Lesen des HTTP-Headers mit Perl |
| PHP | Lesen und Schreiben des HTTP-Headers mit PHP |
| Router | Verbindung über einen Router / Proxy-Server hinweg |
| Verwandte Themen: | HTML, HTTP-Request (HTTP-Anforderung), HTTP Status Code (Erfolg einer HTTP-Anfrage), Ajax (HTTP-Anforderung durch Javascript-Programme) |
| Links |
Ausgewählte
|
Live-Anzeige des HTTP-Headers |
|
| Derzeit abgeschaltet... |
►
Geben sie die Adresse einer beliebigen Webseite ein und klicken sie den Button 'anzeigen'. ► Der HTTP-Header der zurückgesendeten Webseite wird angezeigt. ► Wenn das nicht möglich ist, erhalten sie eine "Fehler"-Webseite - ebenfalls mit HTTP-Header. |
|
♠
Wozu ein HTTP-Header ? Es gibt zahlreiche verschiedene Möglichkeiten für den Inhalt eintreffender Daten-Pakete, z.B. HTML-Quelltexte, Bilder, . . |
• Der HTTP-Header enthält im Klartext einige Informationen, die es dem Empfangs-Programm (z.B. ihrem Browser) erleichtern sollen, die nachfolgenden Daten richtig zu verarbeiten. |
|
♠
Wer sendet den HTTP-Header ? Man erhält auf fast jede Anfrage an einen Webserver als Antwort eine Webseite (mit HTTP-Header): • Wenn die gewünschte Datei (Webseite) existiert, sendet der adressierte Webserver den HTTP-Header und die angeforderten Daten. • Andernfalls sendet der Webserver - wenn er überhaupt erreicht wurde - eine Webseite mit Fehler-Meldung. |
•
Wenn der zutreffende Webserver nicht gefunden wird,
erhalten sie eine Fehlerseite (Timeout) von ihrem Proxy-Server oder von ihrem Browser. • Wenn der Ziel-Server erfolgreich erreicht wird, dieser jedoch das gewünschte Ziel nicht findet, dann erhalten sie die Fehler-Seite vom Ziel-Server. Bedenken sie diese Möglichkeiten, wenn sie Webseiten automatisch auswerten. |
|
♠ Was bedeutet die erste Zeile ? Jeder HTTP Header enthält in der ersten Text-Zeile das Protokoll (HTTP-Version) und den → HTTP Status (Response) Code. |
Der HTTP Status Code ist ein standardisierter Zahlencode, welcher den Erfolg der Browser-Anfrage mitteilt, z.B. OK oder verschiedene Fehler-Meldungen. ♦ Details zum HTTP Status Code |
|
♠ Was bedeutet 'Arbeitszeit' ? Das Programm misst die Zeit vom Absenden des HTTP-Requests bis zum Ende der eingetroffenen Daten. |
Diese 'Round trip time' beträgt im lokalen Netzwerk (LAN) typisch 10..100 ms, im Internet
je nach Verbindung, Auslastung usw. 1..10 s Wenn nach 10 Sekunden noch keine Daten eingetroffen sind (Timeout), beendet das Programm seine Arbeit. |
| Kontrolle: Sie können die Web-Adresse (URL) in der eingebetteten Seite anklicken, um die Webseite selbst dort zu laden. | |
Felder des HTTP-Headers |
|
|
Ein HTTP-Header bietet Platz für sehr viele verschiedene Angaben. Je nach Server
(und Programmierung) sind darin teilweise unterschiedliche Informationen enthalten.
Die Verwendung dieser Daten für eigene Programme ist daher problematisch. Der Header enthält Variable (Felder) in dieser Form: Feldname: Feldwert
Jedes Feld beginnt mit einer neuen Zeile.
|
Die nachfolgende Reihung nach Häufigkeit (in %) ergab sich aus einer Analyse der
HTTP-Header zufällig angeforderter Webseiten. Automatisch arbeitende Programme (Spider, Bot, Crawler...) lassen sich leicht mit → Perl oder → PHP erstellen: Sie 'lesen' z.B. Webseiten und folgen den darin enthaltenen Links, um weitere Webseiten zu analysieren ... ) |
▲ Meistens (>90%) enthaltene Felder:Nur Felder mit hoher Wahrscheinlichkeit können für die Auswertung herangezogen werden. Man sollte sich allerdings niemals darauf verlassen, dass sie in jedem HTTP-Header enthalten sind.Diese 3 Client-Felder enthalten nur Daten, die einem anfragenden Programm ohnehin bekannt sein sollten: • Client-Date Datum & Zeit am anfragenden PC • Client-Peer Adresse und Port des anfragenden PC (d.h. ihres eigenen PC oder ihres Proxy-Servers). • Client-Response-Num normalerweise = 1 |
• Content-Type beschreibt → MIME-Type bzw. → Zeichensatz (für Texte) der nachfolgenden Daten. • Date Datum & Zeit am Server, immer in GMT (d.h. Weltzeit UTC). Bietet bei verlässlichen Servern die Möglichkeit der → Zeit-Synchronisation. • Server Kennung des Servers. Uneinheitlicher Text, kaum für Programme verwendbar. • Connection kündigt an, was mit der Verbindung nach dem Senden der Daten passiert. Der Wert ist meist close, d.h. die Verbindung wird danach geschlossen. |
► Häufige Felder (>40%):• Content-Length) Länge der nachfolgenden Daten in Byte. Der größte Teil umfangreicher Webseiten entfällt auf darin als Verweis enthaltene Bilder, Sounds, Animationen. Diese werden vom Browser nach dem Laden der der 'gastgebenden' Webseite angefordert - Das kann auch ihr Programm (Perl, PHP, ..) tun oder z.B. überlange Daten zurückweisen. |
• Last-Modified Letzte Änderung der nachfolgenden Daten - Ihr Programm kann nachfragen, ob die Daten seit dem letzten Zugriff geändert wurden. • Accept-Ranges Bereitschaft des Servers, Bereichs-Anfragen anzunehmen • Etag Entity-Tag (selten wirklich verwendet, Beschreibung bei W3C) |
▼ Gelegentlich (>20%) anzutreffende Felder:Cache-Control, X-Powered-By, Set-Cookie, Expires
|
▼ Seltene Felder (<10%):
Pragma, P3P, Vary, Cache-Directive, Content-Language, Pragma-Directive, X-Pingback, ...
|
|
Hinweis: Fehler-Webseiten enthalten normalerweise in ihrem HTTP-Header nur wenige Felder !
|
|
HTTP-Header mit Perl |
|
|
Alle gängigen Programmiersprachen bieten die Möglichkeit, eine Verbindung (socket)
zu einem entfernten Dienst (z.B. zu einem Webserver über das Internet) aufzunehmen. Hier werden Scripts in der Programmiersprache → Perl verwendet, welche die Daten (s.o.) als 'Dynamische Webseiten' live anzeigen. |
Das Programm befindet sich am Webserver, fordert von dort aus (!) die gewünschte
Webseite an, analysiert sie und sendet das Ergebnis (den Text des HTTP-Headers) als
Webseite an ihren Browser. Die vom Script erzeugte Webseite wird
als
<iframe> (oben, weiss unterlegt) in diese Webseite eingebettet. ♦ Details zum Lesen von Webseiten mit Javascript-, Perl- oder PHP-Programmen. |
|
Rechts das verwendete Perl Script-Programm (vereinfacht): • Die erste Zeile des Scripts muss einen Verweis auf das Perl-Interpreter-Programm enthalten. Löschen/Ändern sie nach Bedarf. • Das Modul LWP enthält alle Methoden für socket-Verbindungen. Details finden sie im Internet und in der ausführlichen Perl-Dokumentation. • Details zum → Lesen von Webseiten mit Perl • Die Adresse der gewünschten Webseite wird als Argument 'url' an die Variable $url des Script-Programms übergeben. • Falls der ausführende Computer (hier: der Webserver) direkten Zugang zum Internet hat, bleibt Variable $myproxy leer. Andernfalls tragen sie hier die Adresse ihres Proxy-Servers ein. • Zur Ausführung wird ein 'user agent' ($ua) erzeugt. Im Request wird der HEAD angefordert (alternativ können sie mit GET die Webseite selbst anfordern). • Bei Erfolg (is_success) wird der Text des HTTP-Headers angezeigt, bei Misserfolg die Fehlermeldung. Mit einem → Regulären Ausdruck wird der Zeilen-Umbruch HTML-gerecht geändert. Der Text des HTTP-Headers befindet sich in der Variablen $text und kann natürlich an Stelle der Ausgabe auch anders verarbeitet werden. |
#! /usr/bin/perl
use CGI;#! c:\perl\bin\perl.exe ########## Perl Module ########## use LWP; ########## Ausgabe auf Webseite ##########
print "Content-type: text/html\n\n";print "<html>\n"; print "<head><title>HTTP-Header</title></head>\n"; print "<body>\n"; ########## Parameter ##########
my $myq = new CGI;my $url=""; $url = $myq->param('url'); ########## Proxy ##########
my $myproxy="";
# $myproxy="http://192.168.0.1:2345/";
########## Ausfuehrung ##########
my $ua = LWP::UserAgent->new();if(length($myproxy)) {$ua->proxy(http => $myproxy);} my $request = HTTP::Request->new('HEAD',$url); my $response = $ua->request($request); if($response->is_success()) {
my $text=$response->headers_as_string();
}$text=~s/\n/<br>\n/g; print "$text\n"; else {print $response->message();} print "<br>\n"; print "</body>\n</html>\n"; |
|
Sie können das Script mit geringen Änderungen auch als (System-unabhängiges !)
→
Konsolen-Script verwenden. • In diesem Fall fällt das Modul CGI weg, die Web-Adresse wird als Commandline - Argument $ARGV übergeben. • Alle HTML-tags werden aus den print-Anweisungen entfernt. • Dieses Programm erfordert die korrekte Installation der (kostenlosen) Programmiersprache → Perl. • Das Programm wird (je nach Installation) so gestartet: Linux: # http_header.pl http://www.topsoft.at/pstrainer/demo/html/demo.html
Windows (Varianten):
C:\> C:\perl\bin\perl.exe c:\http_header.pl http://www.topsoft.at/pstrainer/demo/html/demo.html
C:\> perl.exe http_header.pl http://www.topsoft.at/pstrainer/demo/html/demo.html C:\> http_header.pl http://www.topsoft.at/pstrainer/demo/html/demo.html |
#! /usr/bin/perl
use LWP;
#! c:\perl\bin\perl.exe ########## Perl Module ########## ########## Ausgabe auf Konsole ##########
print "HTTP-Header\n";
########## Runtime-Argumente ##########
my $url = $ARGV[0] || "http://pstrainer.topsoft.at/";
########## Proxy ##########
my $myproxy="";
# $myproxy="http://192.168.0.1:2345/";
########## Ausfuehrung ##########
my $ua = LWP::UserAgent->new();if(length($myproxy)) {$ua->proxy(http => $myproxy);} my $request = HTTP::Request->new('HEAD',$url); my $response = $ua->request($request); if($response->is_success()) { print $response->headers_as_string();
}else {print $response->message();} print "\n"; |
|
Wenn nur bestimmte Felder aus dem HTTP-Header benötigt werden
(z.B. die Server-Zeit s.o.), dann ist eine andere Version vorteilhafter: • Der HTTP-Header wird an eine Variable (hier $hdr) zugewiesen, danach sind seine Bestandteile verfügbar: • headers_as_string liefert den gesamten Header als String • date liefert die Header-Variable 'Date'. Das Ergebnis ist ein UNIX-Timestamp ($uts) und kann mit üblichen → Datum-&-Zeit Methoden verarbeitet werden. • server liefert die Kennung des Webservers usw. usw. |
$hdr = $ua->head($refurl);
$text = $hdr->headers_as_string(); $uts = $hdr->date+0; $server = $hdr->server; # usw. usw. |
|
Wenn sie ein
→ Konsolen-Script dazu verwenden, die Systemzeit ihres PC zu setzen, dann
können sie dazu die Funktion system verwenden. Sehen sie rechts, wie der entsprechende Systembefehl auf → Linux oder → Windows formuliert wird. |
# Linux
$shellcmd = "date --set=$mytim";
# Windows
$shellcmd = "time $mytim";
# Systembefehl
system($shellcmd);
|
| ♦ Details zum Lesen von Webseiten mit Javascript-, Perl- oder PHP-Programmen. | |
HTTP-Header mit PHP |
|
Funktion get_headers()Das PHP-Modul standard enthält ab Version 5 die Funktion get_headers()Allerdings ist diese Funktion bei manchen Providern abgeschaltet. ( → PHP-Umgebung / disable_functions) |
Live PHP Version:
● phpversion() = 5.3.3-7+squeeze9
Live PHP Modul-Test:
● PHP-Funktion get_headers ist verfügbar.
|
|
Anwendung der Funktion get_headers() Damit wird der HTTP Header einer Webserver-Antwort gelesen und ausgegeben. Der gesamte HTTP-Header ohne Einschränkung wird als Array zeilenweise zurückgegeben. ▲ Die Daten enthalten die wichtige HTTP-Start-Zeile mit dem numerischen und verbalen Antwort-Code:. Eine korrekte Webseite wird so angekündigt: HTTP/1.1 200 OK
Eine typische Fehlerseite wird mit jedem anderen
→ HTTP Status-Code angekündigt:
HTTP/1.1 404 Not Found
▲ Die Daten enthalten meistens die Variable Date und damit die aktuelle Zeit des Servers. Man kann sie daher u.a. zur bequemen Synchronisation der eigenen Systemzeit verwenden. ▲ Die Variablen sind in je einer ganze Zeile organisiert, die man selbst in Name und Wert trennen muss. ▲ Man kann als Argument beliebige URLs eingeben, d.h. von Webseiten auf eigenen und fremden Servern, von Bildern oder anderen Objekten, sogar von nicht vorhandenen Objekten (das provoziert die Fehler-Antwort des Servers). |
HTTP-Header mit PHP lesen: Elegant und einfach:
$url = 'http://www.topsoft.at/pstrainer/demo/html/demo.html';
$hdr = get_headers($url); foreach($hdr as $v) { print "$v <br />";
}
|
|
Live-Ausgabe des PHP-Programmbeispiels get_headers für die
Webseite
http://www.topsoft.at/pstrainer/demo/html/demo.html
● PHP-Funktion get_headers() ist verfügbar.
● Bei Ausführung der Funktion trat jedoch ein Fehler auf.
(Keine Verbindung, Behinderung durch Firewall, ... ? |
|
Funktion apache_response_headers()Mit dieser PHP-Funktion wird der HTTP-Header analysiert, welcher den 'Antwort'-Daten des Webservers vorausgeht.● Die Daten werden in einem assoziativen Array zurückgegeben, d.h. sauber getrennt in Name und Wert. ● Diese Funktion liefert leider nicht alle Header-Variablen, insbesondere nicht Datum und Zeit des Webservers. ● In der Live-Ausgabe (unten) des Beispiels finden sie jenen HTTP-Header, den der Webserver als Ankündigung der jetzt angezeigten Webseite an ihren Browser gesendet hat. ● Ein HTTP-Header wird auch vor anderen Dateien gesendet, z.B. vor Bildern - In diesem Fall wird jedoch mit Content-Type eine andere → MIME-Type angekündigt (für Bilder z.B. image/gif, image/jpeg, image/png,..). |
$arh = apache_response_headers();
foreach ($arh as $h=>$v) { print "$h: $v<br />\n";
}
|
|
Live-Ausgabe des PHP-Programmbeispiels
apache_response_headers für die
Webseite
http://www.topsoft.at/pstrainer/demo/html/demo.html
● Funktion apache_response_headers ist nicht verfügbar !
|
|
Schreiben von HTTP-Header VariablenAlle gängigen Server-Programmiersprachen (→ Perl, → PHP, ..) bieten die Möglichkeit, den HTTP-Header einer am Server erzeugten Datei zu beeinflussen. Das ist z.B. sinnvoll, wenn nicht sichergestellt ist, dass der Webserver die gewünschte → MIME-Type anzeigt.● Die PHP-Funktion header() bietet diese Möglichkeit. ● Im Beispiel rechts wird die MIME-Type der nachfolgenden Datei in der HTTP-Variablen Content-type mit application/xhtml+xml (→ XHTML) festgelegt. ● Funktion header kann beliebig oft aufgerufen werden, um mehrere HTTP-Header Variablen zu schreiben. ● Funktion header muss vor Beginn des eigentlichen Dokuments aufgerufen werden, da sonst der HTTP-Header an dieser Stelle bereits automatisch erzeugt und evtl. sogar abgesendet wurde. |
<?php
header("Content-type: application/xhtml+xml");
?><?xml version="1.0" standalone="no"?> <html xmlns="http://www.w3.org/1999/xhtml"> ... </html> |
Bekanntgabe der MIME-TypeServer-Programmiersprachen (→ Perl, → PHP, ..) sind in der Lage, einen direkten Datenstrom an den Webserver zu senden.Das wird z.B. für dynamische Grafik verwendet, wenn das angeforderte Dokument nur individuelle Bedeutung hat und daher nicht gespeichert wird. ● In diesem Fall verzichtet man darauf, eine Datei zu erzeugen und diese an den Browser zu senden, sondern der Datenstrom läuft direkt vom Script-Programm zum Webserver und weiter zum Browser. ● Ein Datenstrom muss an seinem Anfang die beiden rechts gezeigten Zeilen enthalten. (Die 2. Zeile ist eine Leerzeile) Daraus erstellt der Webserver automatisch den HTTP-Header mit der angegebenen → MIME-Type. ● Erst danach folgt der eigentliche Datenstrom an den Browser. |
Anfang eines HTML-Datenstroms:
print "Content-type: text/html\n\n";
print "<html>"; Anfang eines Grafik-Datenstroms:
print "Content-type: image/png\n\n";
|
Router / Proxy-Server |
|
Die Programmierung von Verbindungen ist aufwändiger, wenn sich das Programm an einem
→ Webserver
im eigenen lokalen Netzwerk (LAN) befindet und das Ziel im Internet.In diesem Fall muss die Verbindung über den zuständigen → Router / Proxy-Server laufen. |
•
Der Router muss an einer fixen Adresse erreichbar sein. Diese ist durch IP-Adresse und Port
festgelegt, z.B. 192.168.0.1:8080 In größeren Netzwerken verlangt der Router zusätzlich eine Authentifizierung (meist mit Name + Passwort). • Man muss Maßnahmen treffen, um die Zugangs-Daten an alle Programme auf allen Geräten (PC) des LAN zu leiten, die mit dem Internet in Verbindung treten sollen. |
Umgebungs-Variable des BetriebssystemsDie Standard-Methode zur Verwaltung der Proxy-Zugangsdaten sind Umgebungs-Variable. Mindestens am Server sollten die hier vorgestellten Variablen definiert sein (die angegebenen Werte sind Beispiele - setzen sie ihre eigenen Daten ein):
FTP_PROXY="http://192.168.0.1:8080"
Allfällige Authentifizierungs-Daten des Routers:
HTTP_PROXY="http://192.168.0.1:8080" HTTPS_PROXY="http://192.168.0.1:8080" NO_PROXY="localhost, 127.0.0.1, 192.168.0.0/24"
HTTP_PROXY_USER="ich"
HTTP_PROXY_PASS="geheim" |
► Die Namen der Variablen können auch in kleinen Buchstaben bezeichnet sein (z.B. http_proxy). Da Linux streng unterscheidet, ist es empfehlenswert, die Variablen in je einer Version mit großen und mit kleinen Buchstaben anzulegen, aber natürlich mit den gleichen Werten. ♥ Es ist sehr empfehlenswert, diese Umgebungs-Variablen auch auf einem Windows-Server anzulegen (nur in Großbuchstaben), da sich daran viele (Opensource) Programme orientieren. ♦ Details zu → Windows Umgebungs-Variablen |
Apache WebserverDie Standard-Konfiguration des Apache Servers gibt die erwähnten Umgebungs-Variablen aus Sicherheits-Gründen nicht an Server-Programme weiter. Am eigenen LAN-Server besteht normalerweise kein Risiko, d.h. man kann diese Daten an die am eigenen Server innerhalb des LAN laufenden Programme weitergeben.Apache-Modul mod_env
Dieses Modul muss geladen werden. Details dazu finden sie in der Konfiguration der jeweiligen
Distribution. Kontrolle mit einem Browser am Server-PC mit dieser
URL (wenn eingerichtet): http://localhost/server-info Manual (wenn eingerichtet): http://localhost/manual
|
Konfigurations-Datei:
Diese Anweisungen sollten in eine der Konfigurations-Dateien eingetragen werden, noch besser
in eine eigene Datei environment.conf
<IfModule mod_env.c>
Damit werden die bezeichneten Umgebungs-Variablen weitergeleitet. Weniger
empfehlenswert ist es, die Variablen-Werte direkt einzusetzen, z.B. mit
PassEnv FTP_PROXY
</IfModule>
PassEnv HTTP_PROXY PassEnv NO_PROXY SetEnv HTTP_PROXY "192.168.0.1:8080"
● Jede Änderung der Konfiguration wird erst nach Neustart des Webservers wirksam. |
Umgebungs-Variable in ProgrammenEin Programm erhält seine Umgebungs-Variablen prinzipiell von seinem Parent (Caller, ...), d.h. von jenem Programm, von dem es gestartet wurde. Das gleiche Programm (z.B. test.pl) erhält unterschiedliche Daten, wenn es z.B. manuell an einer Shell-Konsole gestartet wurde, oder vom Webserver als CGI-Programm, oder vom Cron-Server (Zeit-gesteuert). Es kann verwirrend sein, wenn ein an der Konsole getestetes Programm nicht mehr funktioniert, wenn es vom Webserver verwendet wird.Jede moderne Programmiersprache bietet Zugriff auf die erhaltenen Umgebungs-Variablen, meist in Form von Arrays. Quick & Dirty:
Wenn die Zeit knapp ist, oder wenn man sich ohne Erfolg in den Tiefen des Betriebssystems
verirrt hat, dann kann man einer Variablen auch direkt einen Wert zuweisen wie
$myproxy = '192.168.0.1:8080';
Das funktioniert, hat jedoch Nachteile: Das Programm ist nicht auf andere Server portabel.
Ein
Murphy-Gesetz (en)
besagt, dass Router-Adresse und Port genau dann geändert werden, wenn man
vergessen hat, welche unsauberen Programme in diesem Fall anzupassen sind.♦ Details zu Umgebungs-Variablen in Perl, PHP und zur Konfiguration von PHP. |
Beispiel → Perl:
$myproxy = '';
if(exists($ENV{'HTTP_PROXY'})) { $myproxy = $ENV{'HTTP_PROXY'};
}
Beispiel → PHP:
$myproxy = '';
•
Das
→ Globale Array $_ENV wird nur dann besetzt, wenn in der
→
PHP-Konfigurations-Variablen variables_order ein 'E' eingetragen ist, z.B.:
if(isset($_ENV['HTTP_PROXY'])) { $myproxy = $_ENV['HTTP_PROXY'];
}
variables_order = "EGPC"
Wenn $_ENV nicht besetzt ist, kann man normalerweise das
Element $_SERVER['HTTP_PROXY'] verwenden.• Beachten sie außerdem, dass Linux-Server meist zwischen PHP als Apache-Modul und PHP als CGI-Programm unterscheiden: Jede der beiden Anwendungen wird mit einer eigenen Datei php.ini konfiguriert ! |
|
|
RFC2616 - Hypertext Protocol,
Header Field Definitions,
Response Status Code,
|
|