![]() |
Michael Schröpl
|
|
| |
| E-Mail: | |
|---|---|
| Homepage-URL: |
Bei Fragen zu diesem Beitrag bitte den Autor des Beitrags kontaktieren!
Einige Verbesserungsvorschläge in der aktuellen Version des Artikels wurden dankenswerterweise von Sönke Tesch angeregt.
Normalerweise ist ein URL (uniform resource locator)
die Adresse eines eindeutigen Objektes im World Wide Web.
Tatsächlich aber greifen Benutzer unter Verwendung verschiedener,
vor allem verschieden mächtiger bzw. konfigurierter
Programme (Browser etc.), auf diese Dateien zu und stellen den Inhalt somit
unterschiedlich dar.
Der Versuch, eine Web-Seite, eine Graphik etc. so zu gestalten, daß sie
für jeden Browser funktioniert und gut aussieht, führt zu
entsprechenden Anstrengungen, die Seiten selbst 'intelligent' zu gestalten
(etwa über DHTML), was selbst wiederum die Existenz und Aktivierung weiterer
Fähigkeiten des Browsers (JavaScript etc.) zur Interpretation dieser
Intelligenz erfordert und das Problem letztlich nur verlagert.
Wäre es nicht schöner, wenn der Browser (nicht der Anwender!) dem Webserver mitteilen könnte, was er kann und was er am liebsten mag? Genau das soll das Thema des vorliegenden Artikels sein: Ein Verfahren, nach dem Browser und Webserver den tatsächlichen Inhalt einer über eine eindeutige URL bezeichneten Datei untereinander aushandeln.
Was man dafür nicht braucht, das ist ein nagelneuer
Browser - ganz im Gegenteil, es soll ja mit jedem
Browser funktionieren! Ältere Browser sind bezüglich ihrer Wünsche
höchstens etwas schüchterner; darauf sollte der Verhandlungspartner
eingehen.
Der Webserver ist es nämlich, der die Verhandlung leiten und
auf entsprechenden Wünsche seiner 'digitalen Besucher' angemessen reagieren
muß.
Ein Browser empfängt von einem Webserver nicht nur den Inhalt
einer Datei, sondern gleichzeitig auch weitere Informationen, anhand welcher er
die Verarbeitung des Dateiinhalts vorzunehmen hat.
Zusammen mit einem HTML-Dokument sollte der Webserver dem Browser beispielsweise
einen HTTP-Header mit dem Inhalt Content-type: text/html
senden, um diesem klar zu machen, daß er ein Dokument mit dem MIME-Typ HTML
darzustellen hat (egal, wie die URL dazu heißt - die Endung des Namens ist
nicht immer aussagekräftig genug).
Der Browser muß also die 'Sprache' HTTP (das HyperText Transfer Protocol) verstehen, um zu erkennen, was er tun soll. In derselben Sprache kann er selbst dem Webserver aber auch mitteilen,
und anderes mehr. Einiges davon ist abhängig von den Fähigkeiten des Browsers, anderes von seiner Konfiguration, in welcher der Anwender z. B. eine Prioritätenliste für ihm genehme Landessprachen definieren kann.
Was genau hierbei alles möglich ist, das würde den Rahmen des
vorliegenden Artikels sprengen. Dieser wird sich daher auf einen Spezialfall
konzentrieren: Wir wollen ein Dokument in mehreren verschiedenen
Landessprachen anbieten und den Browser entscheiden lassen,
in welcher Sprache er das Dokument bevorzugt erhalten möchte.
Da dieser Spezialfall im Rahmen der Internationalisierung von Web Sites relativ
häufig auftritt, gibt es neben der allgemeinen Methode zur Verhandlung des
Dateiinhalts noch eine speziellere, die bei eingeschränkter Funktionalität
leichter konfigurierbar ist; da beide Methoden aufeinander aufbauen, wird dieser
Artikel sich mit beiden befassen müssen.
Meine eigenen Erfahrungen basieren auf der Verwendung des Apache-Webservers, welche das hier beschriebene Verfahren mindestens seit der Version 1.1 unter der Bezeichnung server-driven content negotiation realisiert. Da das Verfahren auf dem allgemein bekannten HTTP-Protokoll basiert, sollte es eigentlich auch von anderen Webservern unterstützt werden können ...
Die Idee hierbei ist, daß durch die angesprochene URL auf dem Server nicht die zu übertragende Datei angesprochen wird, sondern eine Textdatei, welche die Verhandlungsstrategie des Webservers festlegt. Diese Datei beschreibt also, in welchen Fällen der Webserver welche tatsächliche Datei zurückliefern soll.
Eine solche Beschreibung besteht aus
Ganz allgemein gesprochen hat die Datei dasselbe Format wie die im RFC822 definierten Angaben eines Mail-Headers.
Zu diesen Eigenschaften gehören insbesondere MIME-Typen, Landessprachen und Qualitätsangaben (das sind Zahlenwerte zwischen 0 und 1).
Nehmen wir an, wir wollen eine Datei mit der URL test.var (in einem
beliebigen Verzeichnis) definieren, welche ein HTML-Dokument in den Sprachen Deutsch
bzw. Englisch beschreiben soll. Dann sollte die Datei test.var etwa folgenden
Inhalt haben:
URI: test # wird von Apache ignoriert URI: test.html.en Content-type: text/html Content-language: en URI: test.html.de Content-type: text/html Content-language: de
Bei der Anforderung von test.var wird in diesem Falle entweder
der Inhalt von test.html.en oder von test.html.de
zurückgeliefert, falls der Browser wenigstens eine der beiden
Landessprachen akzeptiert. Der Browser merkt er von der entsprechenden Verhandlung
gar nichts - in der URL-Zeile sieht der Anwender weiterhin test.var, es ist
keine redirection, die hier statt findet.
Das bedeutet allerdings, daß der Anwender aufgrund der Endung .var
sehen kann, daß hier nicht 'einfach nur' ein HTML-Dokument zurückgeliefert
wird. (Um dies zu verbergen, müßte man die Endung .html als
Variantenbeschreibung definieren, und dies dann beschränkt auf Verzeichnisse
mit den entsprechenden Dokumenten darin - das wiederum geht mit
.htaccess sehr schön dezentral.)
Im obigen Beispiel wurde in beiden Varianten ein MIME-Typ für den Inhalt des
Dokuments definiert. Diese Angabe scheint unverzichtbar zu sein - läßt
man den Content-type an dieser Stelle weg, dann führt die 'Verhandlung'
zu keinem positiven Ergebnis. In diesem Falle sendet der Apache-Webserver einen
HTTP-Statuscode 406 (Not Acceptable) und generiert freundlicherweise dynamisch eine
HTML-Seite mit einer entsprechenden Fehlermeldung sowie Verweisen auf alle
definierten Alternativen (und deren Attributen); der Anwender muß sich dann
explizit eine dieser Dateien aussuchen.
Weil das natürlich keine schöne Lösung ist, sollte der Webmaster
diesen Fall besser aktiv behandeln und einen Standardwert
für diese Auswahl definieren. In unserem Falle wäre das etwa eine
Variante, der keine Sprache zugeordnet ist. Diese gilt dann immer
als 'ausreichend' für die Anforderungen des Browsers, sie wird allerdings mit
niedrigster Priorität als Ergebnis der Verhandlung ausgewählt - genau das,
was wir haben wollen. Die Datei test.var wäre dafür also z. B.
um die Zeilen
URI: test.html.default Content-type: text/html
zu erweitern.
Die Datei test.html.default wird dabei normalerweise identisch mit einer
der bereits vorhandenen Varianten sein. In diesem Falle kann man auf einem UNIX-Server
statt einer Kopie einen symbolic link auf die betreffende Datei anlegen
und verhindert damit, mehrere identische Kopien des Dokuments inhaltlich warten
zu müssen. Natürlich muß der Webserver dazu die Verarbeitung von
symbolic links für das Verzeichnis erlauben
(Options FollowSymLinks in Apache).
An dieser Stelle sei lediglich darauf hingewiesen, daß dieser Mechanismus noch wesentlich mehr kann. Zwei typische Anwendungsbeispiele:
Accept mitteilt, dann kann der Webserver entscheiden,
ob er die PDF- oder ersatzweise die HTML-Version zurückschicken muß,
ohne den Besucher durch die Aufforderung, erst mal zusätzliche Software
zu installieren, zu verschrecken.Das also war die komplizierte Methode. bei der man die Variantendateien
selber schreiben mußte.
Nachdem wir uns jetzt durch diese hindurchgearbeitet haben, kommt die Belohnung:
Wenn man nur einen Teil der verfügbaren Fähigkeiten solcher
Variantenbeschreibungen ausnutzen will, dann kann der Webserver sich diese
selber erzeugen! Um zu versehen, wie er das tut, sind erst einmal wieder
ein paar Grundlagen erforderlich.
Dateien dürfen beim Apache-Webserver generell mehrere Endungen haben
(alles, was durch den ersten Punkt im Namen abgetrennt ist, gilt als Endung - für
Details siehe die mod_mime-Dokumentation des Apache-Webservers).
Insbesondere dürfen als Endungen auftreten:
Beispiel: Die Datei welcome.html.de wird vom Webserver als Dokument
des MIME-Typs text/html und der Landessprache de erkannt werden -
vorausgesetzt, in dessen Konfiguration sind diese beiden Abbildungen korrekt
eingetragen.
Wie motiviert man nun den Webserver, sich eine Variantendatei zu generieren?
Indem man die anzusprechende Datei nicht anlegt, aber für das
entsprechende Verzeichnis die Eigenschaft Options +MultiViews setzt (also die gesetzten Optionen um MultiViews ergänzt).
Als Beispiel soll wieder genau der Fall dienen, der
weiter oben
schon über die statische Variantendatei gelöst worden war.
Wir haben also die Dateien test.html.en und test.html.de zur
Verfügung. Greift ein Besucher nun auf die URL des Dokuments test.html
zu, dann
Im Prinzip macht der Webserver also etwas ganz Ähnliches wie bei der Erzeugung von Fehlerdokumenten, die beim Apache ja schließlich auch konfigurierbar sind - es wird lediglich das Entscheidungsverfahren, welche Datei letztlich zurückgeliefert werden soll, an der passenden Stelle mit dynamischen Daten versehen und abgewickelt. Alles, was wir also zu tun haben, ist es, Dateien mit passenden Namen anzubieten; den Rest erledigt der Webserver von selbst.
Diese MultiViews haben zwei angenehme Nebeneffekte:
test.html.
Für den Besucher ist also - anders als bei den statischen
Variantenbeschreibungen - gar nicht zu erkennen, daß eine dynamische
Bestimmung des Dokumentinhalts stattgefunden hat.Der offensichtliche Nachteil dieses Verfahrens ist der mögliche Performance-Verlust. Wenn der Webserver bei jedem Zugriff auf ein MultiViews-Dokument das Verzeichnis analysieren, die Variantenbeschreibung berechnen und das passende Dokument zurückliefern soll, dann verursacht dies Last auf dem Webserver-Rechner. (Insbesondere sollte man dann nicht zuviele Dokumente in demselben Verzeichnis haben.)
Außerdem ist man eingeschränkt, was die Möglichkeiten
der Formulierung von Verhandlungsstrategien betrifft:
An Prioritätenlisten geht außer der Reihenfolge für Landessprachen
nichts mehr, und komplexe Bedingungen unter Berücksichtigung mehrerer Attribute
des Dokuments sind auch nicht mehr möglich.
Aber gerade daß nur genau die Landessprache als Verhandlungsziel dienen
soll, ist im Zusammenhang mit der Internationalisierung einer Web-Site ein häufig
auftretender Fall. Ein solches Standardproblem läßt sich am besten durch eine
Standardlösung erledigen, und genau dies sind eben die MultiViews von Apache.
Und was tun, wenn man keinen Apache-Webserver hat?
Die Beschreibung dessen, was der Browser an Wünschen gesendet hat, ist auch über Variablen der CGI-Schnittstelle ansprechbar, so daß ein Entwickler das beschriebene Verhalten ggf. durch eine CGI-Anwendung (beispielsweise in der Fehlerbehandlung des Webservers) selbst realisieren könnte.
HTTP_ACCEPT stellt Informationen über die akzeptierten MIME-Typen
im empfangenen HTTP-Header zur Verfügung. (Das scheinen alle bekannten
Browser zu senden, auch Netscape 3 und Microsoft 2; Netscape 4.5 sendet
hier beispielsweise, daß er schon die MIME-Typen img/pjpeg und
img/png kennt.)HTTP_ACCEPT_CHARSET enthält ggf. akzeptierte Zeichensätze.
(Netscape 4.5 sendet hier einen Wert.)HTTP_ACCEPT_ENCODING enthält ggf. akzeptierte Codierungen, also
z. B. die Angabe, daß der Browser auch spezielle (z. B.
komprimierte) Datenformate verarbeiten kann usw. (Netscape 4.5 akzeptiert
beispielsweise schon das encoding gzip, Microsoft Internet
Explorer 5 zusätzlich auch noch deflate.)HTTP_ACCEPT_LANGUAGE enthält ggf. akzeptierte Landessprachen.Diese Variablen sind in der CGI-Norm implizit spezifiziert: CGI liest alles,
was im HTTP-Header kommt, ersetzt '-' durch '_' in Variablennamen, fügt
jeweils die Zeichenkette HTTP_ davor und setzt es ins Environment.
(Wie die Variablen heißen werden, das kann man dem genormten Aufbau
des HTTP-Headers entnehmen.)
Letztlich hilft nur Ausprobieren, was welcher Browser bei geeigneter Konfiguration
senden kann, und prüfen, welche CGI-Variablen in welchen Fällen
tatsächlich gesetzt werden. Gute Defaults muß man für die Verhandlung
ja ohnehin vorsehen ...
Ein besonderes Problem soll wenigstens am Rande erwähnt werden: Was passiert mit mehrdeutigen Inhalten von URLs, die in Zwischenspeichern (Caches von Browsern bzw. Proxy-Servern) aufbewahrt werden sollen bzw. könnten? Wie merkt ein solcher Zwischenspeicher, daß der Inhalt in diesem Falle durch den URL gar nicht eindeutig beschrieben ist? Es droht ja beispielsweise, daß ein Proxy-Server aus seinem Cache eine Seite an einen Browser ausliefert, der im Falle der tatsächlichen Verhandlung mit dem Webserver eine Seite mit ganz anderem Inhalt hätte bekommen müssen (weil die von diesem Browser gelieferten HTTP-Header sich von denen derjenigen Anforderung, welche den Inhalt des Proxy-Cache verursacht hat, unterscheiden?
Der Proxy-Server hat keine realistische Möglichkeit, alle möglichen alternativen Inhalte desselben URL zu speichern - dafür sind es in der Regel einfach zu viele. Ohne entsprechende Information durch den Webserver kann er noch nicht einmal erkennen, daß überhaupt ein Problem vorliegen könnte.
Also muß der Webserver etwas tun. Dafür hat er zwei Moglichkeiten zur Verfügung:
Cache-control: private) und Proxy-Caches (Cache-control: public)
unterscheiden; ältere Browser und vor allem viele Proxy-Server verstehen jedoch
nur HTTP/1.0, und um solchen Proxy-Servern klar zu machen, daß sie die Seite
nicht speichern sollen, müßte man das Speichern leider auch im Browser
verbieten (was die Performance der Übertragung durch die dann zusätzlich
erforderlichen Zugriffe bremst).Vary:). Dabei kann der Server dem Proxy
sogar mitteilen, welche HTTP-Header der Anforderung eine Auswirkung auf das
Ergebnis der Verhandlung hatten, so daß der Proxy sogar in der Lage wäre,
in einem Teil der Fälle diese Verhandlung selbst zu führen (denn er kann
ja speichern, welche HTTP-Header in der ursprünglichen Anforderungen zum
Cache-Inhalt geführt haben). Derzeit unterstützt kein mir bekannter
Proxy-Server diese Art der Verhandlung; einige Proxy-Server (z. B. Squid)
erkennen jedoch immerhin den Vary:-Header und speichern dann den Inhalt
der Seite nicht.
Apache Server: Content Negotiation
Der Artikel zum Thema aus der Apache-Online-Dokumentation.
Apache Server: Module mod_negotiation
Die Beschreibung des Moduls zur Auswertung der content negotiation enthält u. a. die detaillierte Beschreibung des Aufbaus einer Variantendatei (type map).
Apache Server: Module mod_mime
Die Beschreibung des Moduls zur Erkennung von Dateitypen enthält u. a. die detaillierte Beschreibung der Erkennung von Endungen in Dateinamen.
Ein Artikel zum Thema aus dem Apache-Online-Magazin Apache Week.
Homepage der Content Negotiation Working Group
Diese Gruppe befaßt sich mit der Spezifikation von Funktionen zur dynamischen Bestimmung von Objektinhalten und stellt zahlreiche RFCs zu diesem Thema zur Verfügung.
Ein CGI-Skript zur kontrollierten Durchführung eines HTTP-Requests, inklusive einer Protokollfunktion für alle gesendeten und empfangenen HTTP-Header.
© 2007
Impressum, für diese Seite:
michael.schroepl@gmx.de