Teil von SELFHTML aktuell Teil von Artikel Teil von Serverkonfiguration

Michael Schröpl
Alternative Dokumentinhalte via HTTP

nach unten Michael Schröpl
nach unten Einleitung
nach unten HTTP-Header
nach unten Statische Variantenbeschreibungen (type maps)
nach unten Generische Variantenbeschreibungen (multiviews)
nach unten Alternativen
nach unten Content Negotiation und Caches
nach unten Literatur

Michael Schröpl

E-Mail: E-Mail michael.schroepl@gmx.de
Homepage-URL: deutschsprachige Seite http://www.schroepl.net/

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.

nach obennach unten

Einleitung

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ß.

nach obennach unten

HTTP-Header

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 ...

nach obennach unten

Statische Variantenbeschreibungen (type maps)

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:

nach obennach unten

Generische Variantenbeschreibungen (multiviews)

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 nach oben 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:

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.

nach obennach unten

Alternativen

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.

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 ...

nach obennach unten

Content Negotiation und Caches

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:

  1. Er kann HTTP-Header senden, die beliebigen Caches das Speichern der Seite verbieten. In HTTP/1.1 kann man dabei sogar zwischen Browser- (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).
  2. Er kann HTTP-Header senden, die den Inhalt der Seite als Ergebnis einer Verhandlung kennzeichnen (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.

nach obennach unten

Literatur

englischsprachige Seite Apache Server: Content Negotiation

Der Artikel zum Thema aus der Apache-Online-Dokumentation.

englischsprachige Seite 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).

englischsprachige Seite 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.

englischsprachige Seite Content Negotiation Explained

Ein Artikel zum Thema aus dem Apache-Online-Magazin Apache Week.

englischsprachige Seite 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.

englischsprachige Seite HTTP trace

Ein CGI-Skript zur kontrollierten Durchführung eines HTTP-Requests, inklusive einer Protokollfunktion für alle gesendeten und empfangenen HTTP-Header.

Teil von SELFHTML aktuell Teil von Artikel Teil von Serverkonfiguration

© 2007 bereichsübergreifende Seite Impressum, für diese Seite: E-Mail michael.schroepl@gmx.de