Zum Inhalt springen

mod_rewrite

Aus Foxwiki
Die 5 zuletzt angesehenen Seiten:  Spezial:Ungültiger Seitenname » SSH/Tunnel » Programmiersprache » mod_rewrite
(Weitergeleitet von ModRewrite)

mod_rewrite - Umschreibregeln

Beschreibung

Bei der Verwendung von RewriteRule in .htaccess-Dateien ist zu beachten, dass der verzeichnisbezogene Kontext die Dinge ein wenig verändert

  • Insbesondere werden die Regeln als relativ zum aktuellen Verzeichnis betrachtet und nicht als die ursprünglich angeforderte URI
Beispiele
# In httpd.conf
RewriteRule "^/images/(.+)\.jpg" "/images/$1.png"
# In .htaccess im Stammverzeichnis
RewriteRule "^images/(.+)\.jpg" "images/$1.png"
# In .htaccess in images/
RewriteRule "^(.+)\.jpg" "$1.png"

In einer .htaccess in Ihrem Dokumentenverzeichnis wird der führende Schrägstrich aus dem an RewriteRule übergebenen Wert entfernt, und im Unterverzeichnis images wird /images/ daraus entfernt

  • Daher muss Ihr regulärer Ausdruck auch diesen Teil auslassen

8.1.2 mod_rewrite

mod_alias stößt in puncto Flexibilität relativ schnell an seine Grenzen

  • »Swiss Army-Knife of URL manipulation«
  • Hier hat das Modul mod_rewrite erheblich mehr zu bieten
  • Es kann die volle Funktionalität von mod_alias übernehmen, bietet aber noch unzählige weitere Optionen

Der Kern des Moduls ist eine leistungsfähige Engine für mit Perl kompatible reguläre Ausdrücke

Technisch gesehen werden die Funktionen des Moduls an zwei Stellen während der Verarbeitung einer Anfrage aufgerufen: Rewrite-Direktiven, die in der Hauptkonfigurationsdatei stehen, werden während der Umwandlung der angeforderten URL in einen Dateipfad ausgeführt

  • Stehen dagegen Rewrite-Anweisungen in .htaccess-Dateien, werden diese erst in der sogenannten Fixup-Phase befolgt: Da .htaccess-Dateien unterhalb der DocumentRoot liegen, können sie erst nach der eigentlichen URL-Umwandlung gelesen werden
  • Da es an dieser Stelle also eigentlich bereits zu spät für URL-Modifikationen ist, erzeugt eine hier befindliche Rewrite-Regel intern eine Art neue Anfrage

In diesem Abschnitt werden nun zunächst die Direktiven von mod_rewrite beschrieben

  • Anschließend werden einige ausführliche Beispiele behandelt
  • Beides ist lediglich eine Einführung, denn: »Despite the tons of examples and docs, mod_rewrite is voodoo
  • Damned cool voodoo, but still voodoo.« (Brian Moore; zitiert in der mod_rewrite-Dokumentation)

Um erfolgreich mit mod_rewrite arbeiten zu können, benötigen Sie Kenntnisse über reguläre Ausdrücke

  • Eine Übersicht über die wichtigsten Konstrukte finden Sie in Anhang G
  • Eine sehr ausführliche Anleitung bietet [FRIED2007]
  • Relativ gründlich können Sie sich auch von der POD-Dokumentation der Sprache Perl informieren lassen, wenn diese auf Ihrem System installiert ist
  • Geben Sie dazu auf der Konsole Folgendes ein
$ perldoc perlre
RewriteEngine

Rewrite-Funktionalität ein-/ausschalten

Seit Version 1.3

Modul mod_rewrite
Kontext Server, <VirtualHost>, <Directory>, <Location>, <Files>, .htaccess (FileInfo)
Syntax RewriteEngine on|off Standardwert off
Bevor Sie die Funktionalität von mod_rewrite nutzen können, müssen Sie sie mithilfe dieser Direktive einschalten

Beachten Sie, dass die Bibliothek PCRE (Perl-Compatible Regular Expressions), die nicht nur in Apache, sondern in vielen verschiedenen Programmen und Sprachen eingesetzt wird, nicht ganz denselben Leistungsumfang besitzt wie das Pattern Matching in Perl selbst

RewriteEngine On

Anders als zahlreiche andere Konfigurationseinstellungen wird diese Aktivierung von RewriteEngine nicht an Subkontexte vererbt: Wenn Sie die RewriteEngine beispielsweise im Server-Kontext einschalten, gilt dies nicht für <VirtualHost>-, <Directory>- oder sonstige Container

  • Die Funktion muss deshalb in jedem gewünschten Kontext explizit aktiviert werden
  • Insofern hat das ausdrückliche Ausschalten mittels RewriteEngine Off in der Praxis keine besonders große Bedeutung
RewriteRule Definiert Rewrite-Regeln

Seit Version 1.3; cookie-Flag seit 2.0.40 Modul mod_rewrite Kontext Server, <VirtualHost>, <Directory>, <Location>, <Files>, .htaccess (FileInfo) Syntax RewriteRule [!]RegExp Ersatztext [Flag, ...] Standardwert nicht gesetzt

Dies ist die wichtigste Direktive von mod_rewrite

  • Sie kann unabhängig von anderen Direktiven dieses Moduls aufgerufen werden und funktioniert dann ähnlich wie AliasMatch oder RedirectMatch
  • Standardmäßig werden allerdings alle untereinanderstehenden RewriteRule-Anweisungen nacheinander ausgeführt
  • Dabei wird die URL unter Umständen mehrfach umgeschrieben

Das erste Argument ist ein beliebiger Perl-kompatibler regulärer Ausdruck

  • Die Rewrite-Regel wird angewendet, wenn das angegebene Muster im URL-Pfad der Client-Anfrage gefunden wird
  • Optional können Sie dem regulären Ausdruck ein Ausrufezeichen voranstellen
  • In diesem Fall wird die RewriteRule nur beachtet, wenn er nicht zutrifft

Der Ersatztext ist ein beliebiger String

  • Darin können Sie eine Reihe besonderer Elemente verwenden
  • $1 bis $9: Diese Platzhalter entsprechen den im regulären Ausdruck gefundenen Teilausdrücken, die Sie in Klammern setzen
  • Die Nummerierung erfolgt von links nach rechts, bei verschachtelten Klammern von außen nach innen
  • %1 bis %9: Mithilfe dieser Platzhalter können Sie Bezug auf geklammerte Ausdrücke aus RewriteCond-Direktiven nehmen
  • %{VAR}: Dies ermöglicht das Einbinden der angegebenen Server-Variablen
  • An dieser Stelle sind die folgenden Variablen zulässig
  • Einige HTTP-Anfrage-Header
  • Ihr Name wird komplett in Großbuchstaben gesetzt; Bindestriche werden durch Unterstriche ersetzt
  • Die zulässigen Header sind HTTP_USER_AGENT, HTTP_REFERER, HTTP_COOKIE, HTTP_

FORWARDED, HTTP_HOST, HTTP_PROXY_CONNECTION und HTTP_ACCEPT (ihre Bedeutung können Sie in Kapitel 2, »Funktionsweise von Webservern«, nachlesen)

  • Informationen über Anfrage und Verbindung: REMOTE_ADDR, REMOTE_HOST, REMOTE_USER, REMOTE_IDENT, REQUEST_METHOD, SCRIPT_FILENAME, PATH_

INFO, QUERY_STRING und AUTH_TYPE

  • Näheres über die meisten dieser Variablen steht in Kapitel 14, »CGI«
  • Informationen über den Server selbst: DOCUMENT_ROOT, SERVER_ADMIN, SERVER_NAME, SERVER_ADDR, SERVER_PORT, SERVER_PROTOCOL und SERVER_

SOFTWARE

  • Viele dieser Variablen dürften Ihnen bekannt vorkommen, weil es ähnlich lautende Konfigurationsdirektiven gibt (siehe Kapitel 6, »Grundkonfiguration«)
  • Ansonsten werden auch diese Variablen in Kapitel 14, »CGI«, erläutert
  • Datum und Uhrzeit: TIME_YEAR, TIME_MON, TIME_DAY, TIME_HOUR, TIME_MIN, TIME_SEC, TIME_WDAY und TIME
  • Die Namen dieser Variablen dürften selbsterklärend sein
  • API_VERSION: Diese Nummer entspricht der in Kapitel 5, »Apache in Betrieb nehmen«, angesprochenen Module Magic Number; sie gibt unter anderem Auskunft darüber, welche Versionen kompilierter DSO-Module mit der aktuellen Server-Version kompatibel sind
  • Beispielwert

20051115:15 (Apache 2.2.9)

  • THE_REQUEST: Dies ist die vollständige Startzeile der HTTP-Client-Anfrage

Beispiel: GET /dir/file HTTP/1.1

  • REQUEST_URI: die angeforderte Ressource
  • REQUEST_FILENAME: der lokale Pfad- und Dateiname der angeforderten Ressource
  • IS_SUBREQ: Diese Variable besitzt den Wert true, wenn es sich bei der aktuellen HTTP-Anfrage nicht um eine Client-Anfrage, sondern um eine interne Unteranfrage handelt

Abgesehen davon gibt es noch einige Sonderformen

  • %{ENV:Variable} liefert die angegebene Umgebungsvariable
  • Variablen ohne das Präfix ENV sind keine Umgebungsvariablen, sondern spezielle mod_rewrite-Server-Variablen – selbst dann, wenn sie denselben Namen tragen (und in aller Regel natürlich denselben Wert liefern)
  • %{HTTP:Header} liefert den Wert des angegebenen HTTP-Anfrage-Headers

– beispielsweise erhalten Sie über %{HTTP:User-Agent} den Namen des anfragenden Client-Programms

  • Hier stehen auch Header zur Verfügung, für die nicht eine Standardform wie %{HTTP_REFERER} definiert ist
  • %{LA-U:Variable} führt eine URL-basierte interne Unteranfrage durch, um den Wert der angegebenen Variablen zu ermitteln
  • Dieser Mechanismus wird für einige Variablen benötigt, deren Wert erst nach der URLUmwandlung (die Phase, während der mod_rewrite im Server-Kontext arbeitet) feststeht
  • Ein gutes Beispiel ist der Benutzername des entfernten Benutzers, %{LA-U:Remote-User} – Authentifizierungsinformationen stehen erst später in der Anfrageverarbeitung zur Verfügung.2
  • %{LA-F:Variable} ist eine dateinamenbasierte Unterabfrage
  • In der Regel besteht kein Unterschied zur URL-basierten Form %{LA-U:Variable}
  • ${Map-Name:Schlüssel[|Standardwert]}: Mithilfe von RewriteMap können Sie eine externe Datei definieren, in der sich Schlüssel-Wert-Paare befinden

Diese Formulierung ermöglicht es Ihnen, auf die durch Map-Name bezeichnete RewriteMap zuzugreifen und daraus den Wert auszulesen, der für Schlüssel definiert ist

  • Optional können Sie einen Standardwert angeben, der verwendet wird, wenn der Schlüssel in der Map nicht gefunden wird

Als drittes Argument können optional zahlreiche Flags angegeben werden

  • Diese werden durch Kommas voneinander getrennt und stehen in eckigen Klammern

Folgende Flags sind definiert

  • redirect|R[=Statuscode]: Normalerweise sorgt RewriteRule für eine einfache interne URI-Änderung
  • Wenn Sie eine Weiterleitung durchführen möchten, müssen Sie die Ersatz-URL mit http:// beginnen
  • Mithilfe dieses Flags können Sie zusätzlich einen bestimmten Statuscode setzen: temp (302 Found –

Standard), permanent (301 Moved Permanently), seeother (303 See Other) beziehungsweise einen numerischen Wert aus dem 3xx- oder 4xx-Bereich

  • forbidden|F: Dies setzt den Statuscode 403 Forbidden: Wenn der Mustervergleich zutrifft, wird dem Client der Zugriff auf die angeforderte Ressource ausdrücklich verboten
  • gone|G: Durch den Statuscode 410 Gone wird dem Client mitgeteilt, dass die angeforderte Ressource dauerhaft entfernt worden ist
  • proxy|P: Dieses Flag beendet das Rewriting – nachfolgende RewriteRuleAnweisungen werden nicht mehr beachtet
  • Die Ziel-URL wird an mod_proxy

2 Das ist nicht der Fall, wenn Sie RewriteRule in einem Verzeichniskontext einsetzen – hier können Sie einfach %{REMOTE_USER} verwenden

weitergereicht und erzeugt eine Proxy-Anfrage

  • Beachten Sie, dass der Ersatztext eine vollständige URL sein muss, die mit http:// beginnt
  • last|L: Mit diesem Flag können Sie dafür sorgen, dass das Rewriting sofort beendet wird; weitere RewriteRules werden nicht mehr beachtet
  • END (seit Version 2.3): Wirkt wie L, verhindert aber zusätzlich die Ausführung eventueller RewriteRules in .htaccess-Dateien
  • next|N: Dies sorgt dafür, dass das komplette Rewriting erneut durchgeführt wird, beginnend bei der ersten RewriteRule in der Reihe
  • Dies ist beispielsweise für das mehrfache Suchen und Ersetzen eines Musters nützlich
  • Die Bedingung beziehungsweise das Suchmuster muss allerdings so beschaffen sein, dass irgendwann ein Abbruch stattfindet – andernfalls kommt es zu einer Endlosschleife
  • Ein [L]-Flag in einer weiter oben stehenden Regel kann das Problem natürlich ebenfalls lösen
  • chain|C: Dieses Flag ermöglicht eine Art logisches Und mit Short-Circuit-Verfahren: Die nächste RewriteRule wird nur dann überhaupt geprüft, wenn die aktuelle zutrifft
  • Andernfalls werden alle mittels [C]-Flags verketteten Regeln übersprungen
  • type|T=MIME-Type: Dies sorgt dafür, dass der Zieldatei der angegebene MIMEType für den Content-Type-Header zugewiesen wird
  • nosubreq|NS: Die Regel soll nur angewendet werden, wenn die aktuell verarbeitete Anfrage eine echte Client-Abfrage und keine interne Unterabfrage ist
  • nocase|NC: Beim Suchmuster wird nicht zwischen Groß- und Kleinschreibung unterschieden
  • qsappend|QSA: Wenn der Ersatztext ein Fragezeichen enthält und auf diese Weise einen Query-String bildet, sollen die entsprechenden Daten den bereits vorhandenen Query-String nicht ersetzen, sondern an diesen angehängt werden
  • qsdiscard|QSD (seit Version 2.4): Falls die ursprüngliche URL einen Query-String enthält, wird dieser nicht wie üblich beibehalten, sondern entfernt
  • QSD hat dabei Vorrang vor QSA
  • noescape|NE: Im Ersatztext soll kein URL-Escaping durchgeführt werden
  • Dies ist z. B. nützlich, wenn %-Zeichen nicht codiert werden, sondern manuelles Escaping bewirken sollen
  • passthrough|PT: Das Ergebnis der RewriteRule wird so aufbereitet, dass der nächste Handler, der sich um die Umsetzung der Anforderungs-URL in einen Dateinamen kümmert, damit zurechtkommt
  • Intern wird das Feld request_req>uri wieder auf den Wert von filename gesetzt
  • Dieses Flag ist beispielsweise erforderlich, wenn mod_rewrite und mod_alias gemeinsam verwendet werden
  • skip|S=n: Die nächsten n RewriteRules sollen übersprungen werden
  • Dieses Flag ist für if/else-artige Fallentscheidungen geeignet
  • env|E=VAR:VAL: Setzt die angegebene Umgebungsvariable (VAR) auf den genannten Wert (VAL)
  • cookie|CO=Name:Wert[:Lifetime[:Pfad]]: Dies sorgt dafür, dass ein Cookie gesetzt wird
  • Name und Wert sind obligatorisch, während Lifetime (Gültigkeitsdauer) und Pfad (Geltungsbereich) des Cookies optional sind
  • Cookies ohne Gültigkeitsdauer sind sogenannte Session-Cookies, die am Ende der Client-Sitzung automatisch gelöscht werden
Beachten Sie zu guter Letzt Folgendes

Wenn Sie RewriteRule in Verzeichniskontexten einsetzen, wird der Pfad bis zum entsprechenden Verzeichnis vor dem Rewriting aus der URL entfernt und erst danach wieder hinzugefügt

  • Eine Ausnahme tritt ein, wenn der Ersatzstring mit http:// beginnt

RewriteCond Bedingung, unter der Rewrite durchgeführt wird

Seit Version 1.3 Modul mod_rewrite Kontext Server, <VirtualHost>, <Directory>, <Location>, <Files>, .htaccess (FileInfo) Syntax RewriteCond Teststring RegExp Standardwert nicht gesetzt

Diese Direktive formuliert gewissermaßen eine Vorbedingung für nachfolgende RewriteRule-Anweisungen, die zusätzlich zu dem RegExp-Match zutreffen muss

  • Wenn Sie mehrere RewriteCond-Direktiven untereinanderschreiben, müssen sie standardmäßig alle zutreffen, damit die RewriteRule-Anweisungen beachtet werden

Das erste Argument, der Teststring, ist einfacher Text, der zusätzlich folgende Konstrukte enthalten kann

  • $1 bis $9: Referenz auf einen geklammerten Teilausdruck aus dem regulären Ausdruck der nachfolgenden RewriteRule-Direktive
  • %1 bis %9: Referenz auf einen geklammerten Teilausdruck im regulären Ausdruck der vorigen RewriteCond
  • ${Map-Name:Schlüssel[|Standardwert]}: Referenz auf den angegebenen Schlüssel in der durch Map-Name bezeichneten RewriteMap
  • %{VAR}: Zugriff auf die benannte Server-Variable (Näheres weiter oben in der Beschreibung der Direktive RewriteRule und in Kapitel 14, »CGI«)

Das zweite Argument von RewriteCond ist ein mit Perl kompatibler regulärer Ausdruck, mit dem das erste Argument verglichen wird

  • Diesem können Sie optional ein Ausrufezeichen voranstellen – die RewriteCond gilt dann nur als zutreffend, wenn der Ausdruck nicht passt
  • Alternativ können Sie statt eines regulären Ausdrucks auch folgende Spezialformulierungen verwenden
  • <String: Trifft zu, wenn das erste Argument im Alphabet (genauer gesagt in der Zeichensatzreihenfolge) vor dem hier angegebenen String steht
  • >String: Wahr, wenn das erste Argument in der Zeichensatzreihenfolge nach diesem Text folgt
  • =String: Zutreffend, wenn das erste Argument genau mit dem Teststring identisch ist
  • Dies ist eine praktische Kurzfassung für den regulären Ausdruck

^String$

  • -d: Wahr, wenn das erste Argument ein Verzeichnis (Directory) ist
  • -f: Ist zutreffend, wenn das erste Argument eine normale Datei (File) ist
  • -s: Zutreffend, wenn das erste Argument eine Datei mit Inhalt ist – erkennbar an einer Dateigröße (Size) von über 0 Byte
  • -l: Wahr, wenn das erste Argument ein symbolischer Link ist
  • -F: Dieses Argument führt eine Unterabfrage durch, um zu überprüfen, ob es sich beim ersten Argument um eine tatsächlich verfügbare Datei handelt
  • -U: Führt ebenfalls eine Unterabfrage durch und prüft, ob das erste Argument eine verfügbare URL ist

Alle diese Sonderargumente können Sie ebenfalls mit einem vorangestellten Anführungszeichen verneinen

Das optionale dritte Argument sind auch hier Flags, die durch Kommata getrennt werden und in eckigen Klammern stehen

  • Die folgenden beiden Flags sind hier definiert
  • NC|nocase Im regulären Ausdruck des zweiten Arguments soll nicht zwischen Groß- und Kleinschreibung unterschieden werden
  • OR|ornext Zwischen der aktuellen und der nächsten RewriteCond-Anweisung wird ein logisches Oder gesetzt – es genügt, wenn eine von ihnen zutrifft
  • Der Normalfall ist dagegen ein logisches Und: Alle aufeinanderfolgenden RewriteCondDirektiven müssen zutreffen, damit die nachfolgenden RewriteRule-Anweisungen beachtet werden
RewriteBase

Basis-URL für Rewrite-Verzeichnisse

Seit Version 1.3 Modul mod_rewrite Kontext <Directory>, <Location>, <Files>, .htaccess (FileInfo) Syntax RewriteBase URL-Pfad Standardwert aktuelles Verzeichnis (Näheres siehe Text)

Diese Direktive gibt den Basis-Verzeichnispfad für Rewrite-Operationen an

  • Dies kann für RewriteRule-Operationen in <Directory>-Containern verwendet werden

Der Standardwert ist der tatsächliche Verzeichnispfad im Dateisystem

  • Wie bereits erwähnt, wird bei RewriteRule-Direktiven in untergeordneten Kontexten zunächst der URL-Pfad dieser Kontexte entfernt; nach erfolgtem Rewrite wird er wieder hinzugefügt

In der Regel ist die Voreinstellung in Ordnung

  • Geändert werden muss sie nur, wenn der URL-Pfad des Containers nicht dem Verzeichnispfad entspricht – dies ist z. B. bei Verzeichnissen der Fall, die durch Alias-Anweisungen eingebunden wurden
Beispiel
  1. Einbinden des Verzeichnisses /woanders unter der URL /test Alias /test /woanders
  2. Einstellungen für das Verzeichnis /woanders
<Directory /woanders>
# URL-Pfad für Rewrites muss auf /test gesetzt werden RewriteBase /test RewriteRule ..
</Directory>
RewriteMap

Schlägt einen Rewrite-Schlüssel in einer Map-Datei nach

Seit Version 1.3; DBM-Auswahl seit 2.0.41 Modul mod_rewrite Kontext Server, <VirtualHost> Syntax RewriteMap Map-Name Map-Typ:Map-Datei Standardwert nicht gesetzt

Diese Direktive bindet eine Datei mit Schlüssel-Wert-Paaren für das Nachschlagen von Rewrite-Regeln ein

  • Solche RewriteMap-Dateien sind praktisch, wenn Sie in RewriteRule-Ersatztexten oder RewriteCond-Teststrings häufiger bestimmte Textbausteine benötigen: Sie können den Schlüssel angeben, und der entsprechende Wert wird automatisch eingesetzt

In einer RewriteRule- oder RewriteCond-Direktive erfolgt der Zugriff auf die RewriteMap nach folgendem Schema

${Map-Name:Schlüssel}

Aus Sicherheitsgründen ist es besser, zusätzlich einen Standardwert anzugeben Dieser wird eingesetzt, wenn der Schlüssel nicht gefunden wird

  • Die Schreibweise sieht so aus
${Map-Name:Schlüssel|Standardwert}

Der Map-Name entspricht dem ersten Argument von RewriteMap

  • Es handelt sich um einen beliebigen String, den Sie sich aussuchen können
  • Das zweite Argument ist die durch Doppelpunkt getrennte Kombination aus dem Typ der RewriteMap und dem entsprechenden Dateinamen
  • Folgende Typen sind definiert
  • txt: einfache Textdatei Dies ist die einfachste Art einer Map-Datei
  • Jede Zeile enthält ein durch Leerzeichen getrenntes Schlüssel-Wert-Paar
  • Leerzeilen und Kommentare (Text nach einer #) werden ignoriert
  • Sollten Sie einen Schlüssel mehrfach definieren, gilt das erste Vorkommen
  • Hier ein Beispiel für eine solche Definition
RewriteMap mailmap txt:/Pfad/von/mailmap.txt

Die Datei könnte beispielsweise folgendermaßen aussehen

  1. mailmap.txt – E-Mail-Adressen von Mitarbeitern ps peterschmitz@mynet.de # Peter Schmitz, Vertrieb bm bertmueller@mynet.de # Bert Müller, Technik ab antonbecker@mynet.de # Anton Becker, IT

Wenn Sie nun in einer URL – z. B. in einem Query-String – eine der E-MailAdressen benötigen, funktioniert der Zugriff in etwa so

${mailmap:ps|info@mynet.de}

Damit nicht die Gefahr entsteht, gar keine E-Mail-Adresse zu erhalten, wird die Hauptfirmenadresse info@mynet.de als Standardwert verwendet

  • rnd: Textdatei mit Werten zur zufälligen Auswahl Auch dieser Map-Typ ist eine gewöhnliche Textdatei
  • Die Besonderheit besteht darin, dass Sie für jeden Schlüssel mehrere, durch Pipe-Zeichen (|) getrennte Werte angeben können
  • Bei jedem Zugriff auf den Schlüssel wählt Apache einen der Werte zufällig aus
  • Interessant ist dieses Verfahren für vielfältige Zwecke: Naheliegend wäre die zufällige Auswahl eines Bildes, eines Zitats oder einer URL aus einer Linkliste
  • Selbst für einfaches Load-Balancing taugt das Verfahren: Aus einer Liste von Host-Namensbestandteilen wie www1 bis www9 könnte bei jeder Anfrage ein anderer ausgewählt werden
  • Näheres dazu finden Sie in Kapitel 12, »Skalierung und Performance-Tuning«

Das folgende Beispiel ermöglicht die Auswahl eines Bildes und einer Link-URL aus Alternativenlisten

RewriteMap linkmap rnd:/Pfad/von/linkmap.txt

Die zugehörige Datei sieht möglicherweise so aus

# linkmap.txt – zufällige Bild- und Link-URLs bild photo.jpg|grafik.gif|bild.png|beispiel.jpg link /info/index.html|/news/index.html|/catalog/index.html

Die folgende RewriteRule wandelt einen Aufruf von /images/zbild in ein zufällig ausgewähltes Bild um

RewriteRule ^/images/zbild /images/${linkmap:bild|default.gif}
  • dbm: DBM-Datei anstelle der einfachen Textdatei Wenn Sie eine RewriteMap mit sehr vielen Zuordnungen benötigen, kann es sich günstig auf die Performance auswirken, statt der einfachen Textdateien datenbankartige DBM-Dateien zu verwenden
  • Der Inhalt einer solchen Datei ist mit der Textdatei identisch, wird aber binär gespeichert und mit einem Index versehen

Je nach Plattform stehen nicht alle Formen von DBM-Dateien (SDBM, GDBM, NDBM usw.) zur Verfügung

  • Recht empfehlenswert sind SDBM-Dateien: Zwar sind einige andere DBM-Typen noch schneller, aber dafür wird SDBM auf vielen Plattformen unterstützt und ist sowohl in Apache als auch beispielsweise in Perl automatisch eingebaut
  • Andere DBM-Typen müssen Sie mithilfe der in Kapitel 4, »Apache kompilieren und installieren«, vorgestellten configureEinstellungen wie --with-gdbm bei der Kompilierung hinzufügen

Es ist wichtig, dass Sie folgende Beschränkung von SDBM-Dateien beachten Ein Schlüssel und sein Wert dürfen zusammen nicht länger als 1.000 Byte sein

  • Natürlich ist es unwahrscheinlich, dass Sie in URLs jemals eine solche

Textmenge benötigen – aber bei der per Rewrite gesteuerten Erzeugung von Query-Strings könnte es immerhin vorkommen Sie können beispielsweise das folgende kleine Skript verwenden, um eine solche Datei aus Benutzereingaben zu erzeugen (es befindet sich zusätzlich auf der beiliegenden DVD-ROM)

#!/usr/bin/perl -w use strict;
use Fcntl;
use SDBM_File;
# Name der MAP-Datei aus Kommandozeilenargument / Standard my $mapfile = $ARGV[0] || 'map';
# Hash %map mit tie() an $mapfile binden tie(my %map, 'SDBM_File', $mapfile, O_RDWR|O_CREAT, 0666)
|| die "Kein Zugriff auf $mapfile: $!\n";
# Bisherige Einträge anzeigen print "Vorhandene Werte in $mapfile:\n";
foreach my $key (keys %map) {
my $entry = $map{$key};
print "$key\t$entry\n";
}
# Eingabe neuer Einträge print "Bitte 'Name Wert'-Paare eingeben.\n"
print "[Einfaches ENTER zum Beenden.]\n";
while (my $line = <>) {
chomp $line;
last if ($line eq );
if ($line !~ /^[^\s]+\s+[^\s]+/) {
print "Falsches Format: $line\n";
next;
}
my ($key, $val) = split (/\s+/, $line);
$map{$key} = $val;
}

Wenn Sie das Programm ausführen, werden zunächst die vorhandenen Werte angezeigt

  • Anschließend können Sie so lange neue eingeben, bis Sie einfach

(¢) drücken

  • In der Ausführung sieht das etwa so aus
$ chmod a+x sdbmedit.pl
$ ./sdbmedit.pl mymap

Vorhandene Werte in mymap

logo /images/common/logo.gif photo /images/photos/photo1.jpg Bitte 'Name Wert'-Paare eingeben

[Einfaches ENTER zum Beenden.]

head /images/common/headline.gif bullet /images/common/bullet.gif logo /images/common/neulogo.gif

Wenn Sie den Namen eines bereits vorhandenen Schlüssels eingeben (hier z. B. logo), wird dessen bisheriger Wert überschrieben Die praktische Funktion tie()bindet eine Variable an ein Package beziehungsweise eine Klasse

  • Im vorliegenden Beispiel führen Änderungen der Variablen dazu, dass auch die SDBM-Datei automatisch geändert wird
  • Bei SDBM_File werden folgende Argumente für tie() benötigt
  • Name der Hash-Variablen
  • der Klassenname SDBM_File
  • der Dateiname für die SDBM-Datei
  • Sie sollten einen Namen ohne Endung verwenden, weil automatisch die beiden Dateien NAME.pag und NAME

dir erzeugt werden

  • open-Konstanten für Lesen, Schreiben usw. Die symbolischen Konstanten werden durch Fcntl bereitgestellt
  • O_RDWR öffnet die Datei zum Lesen und Schreiben; O_CREAT erzeugt sie neu, falls sie noch nicht existieren sollte
  • Berechtigungen für die Datei. 0666 bedeutet, dass zunächst einmal jeder die Datei lesen und hineinschreiben darf
  • Diese Berechtigungen werden durch die umask des aktuellen Benutzers modifiziert

Wenn eine Eingabe nicht mindestens ein Zeichen für den Schlüssel, ein Leerzeichen und ein Zeichen für den Wert enthält, wird sie mit einer Fehlermeldung zurückgewiesen; next() überspringt den Rest des Schleifenrumpfes und beginnt sofort den nächsten Schleifendurchlauf Alternativ steht seit Apache 2.1-beta das neue Hilfsprogramm httxt2dbm zur Verfügung, das textbasierte Map-Dateien automatisch in DBM-Dateien umwandelt

  • Das Syntaxschema dieses Programms sieht wie folgt aus
httxt2dbm [-v] [-f DBM-Typ] –i Eingabedatei –o Ausgabedatei

Die Kommandozeilenparameter haben die nachfolgende Bedeutung

  • -v (verbose) sorgt für eine ausführlichere Ausgabe
  • -f ermöglicht Ihnen die Angabe des DBM-Typs (GDBM, SDBM, DB oder NDBM)
  • Wenn Sie keinen Typ angeben, wird der APR-Standardwert gewählt
  • -i gibt die Textdatei an, aus der die Eingabedaten stammen sollen
  • Das Format muss den Angaben entsprechen, die weiter oben für den Map-Typ txt gemacht wurden
  • -o dient der Angabe eines Namens für die Ausgabedatei

Das folgende Beispiel wandelt die Datei mymap.txt in die SDBM-Datei mymap um

# httxt2dbm –f SDBM –i mymap.txt –o mymap

Die fertige SDBM-Datei können Sie folgendermaßen als Map-Datei definieren

RewriteMap mymap dbm:/Pfad/von/mymap

  • int: Interne Funktion verwenden Statt einer richtigen map soll eine der folgenden internen Funktionen verwendet werden
  • toupper: Der bisherige Wert des »Schlüssels« wird komplett in Großbuchstaben konvertiert
  • NurEinTest würde zu NUREINTEST
  • tolower: Der Wert wird in Kleinbuchstaben umgewandelt
  • Aus NurEinTest wird in diesem Fall nureintest
  • escape: Sonderzeichen im Text werden URL-codiert
  • Günther Möller wird z. B. durch G%FCnther+M%F6ller ersetzt
  • unescape: Eventuelle URL-codierte Sonderzeichen werden in ihre normale Form umgewandelt
  • Das vorige Beispiel könnte in diesem Fall umgekehrt ausgeführt werden

Die Einbindung einer solchen Funktion als Map funktioniert z. B. so

RewriteMap klein int:tolower
  • prg: eigenes Programm ausführen Der letzte Map-Typ ist der komplizierteste, aber auch der vielseitigste: Es wird ein externes Programm aufgerufen, das beliebige Manipulationen am URLInhalt durchführen kann
  • Für ein solches Programm gelten folgende Voraussetzungen
  • Der zu ändernde Text (der jeweilige »Schlüssel«) wird automatisch über STDIN eingegeben
  • Das Ergebnis muss auf STDOUT geschrieben werden
  • Da das Programm nur einmal beim Start von Apache aktiviert wird, benötigt es eine Eingabeschleife, die die verschiedenen Anforderungen nacheinander entgegennimmt
  • Es darf keine gepufferte Ausgabe stattfinden
  • Da bei einer solchen Änderung so gut wie nie genügend Text zusammenkommt, um den Ausgabepuffer zu füllen, bleibt das Programm – und damit die Anfrage – hängen
  • In Perl können Sie für STDOUT den Autoflush-Modus aktivieren, um dies zu verhindern
  • Fügen Sie dazu am Anfang Ihres Skripts folgende Zeilen ein

select (STDOUT); $| = 1;

  • Um verschiedene Zugriffe auf Ihr Map-Programm zu serialisieren, müssen Sie mit der gleichnamigen Direktive eine RewriteLock-Datei definieren

Hier ein recht nützliches Beispiel: Das folgende Perl-Skript liefert für den Schlüssel now (und als Standardwert für nicht gefundene Schlüssel) das aktuelle Datum im Format 2008-08-26

  • yesterday bringt das ebenso formatierte Datum des Vortags; Schlüsselnamen wie minus3 oder minus7 gehen die entsprechende Anzahl von Tagen zurück
  • Wenn Sie jeden Tag eine bestimmte Datei erzeugen, in deren Namen für spätere Archivzwecke das aktuelle Datum vorkommt, ist es praktischer, sie über eine solche Rewrite-Option zu verlinken, als später umzubenennen
  • Hier der Code für das Beispiel
#!/usr/bin/perl -w
# datemap.pl – Datum für URL-Umwandlung ermitteln use strict;
select (STDOUT);
$| = 1; # Autoflush-Modus my $daysec = 24 * 60 * 60; # 1 Tag in Sekunden
# Monatsnamen aus scalar(localtime) in Nummern umwandeln
my %months = (Jan => '01', Feb => '02', Mar => '03', Apr => '04', May => '05', Jun => '06', Jul => '07', Aug => '08', Sep => '09', Oct => '10', Nov => '11', Dec => '12');
# "Schlüssel" von STDIN lesen while (my $key = <STDIN>) {
chomp $key;
my $now = time(); # Aktuelles Datum/Uhrzeit if ($key eq 'yesterday') {
$now -= $daysec; # 1 Tag abziehen
} elsif ($key =~ /^minus(\d+)/) {
$now -= $daysec * $1; # n Tage abziehen
}
# Datum umwandeln –
# liefert z.B. "Thu Aug 28 12:06:22 2008"
my $timestr = scalar (localtime ($now));
# Ergebnis in Einzelteile zerlegen
my ($wd, $month, $day, $t, $year) =
split (/\s+/, $timestr);
# Monatsnummer ermitteln my $monthnr = $months{$month};
# '0' vor dem Tagesdatum, falls < 10
$day = ($day < 10) ? "0$day" : $day;
# Komplettes Datum zusammensetzen – z.B. 2008-08-19
my $output = "${year}-${monthnr}-${day}";
# Ausgabe auf STDOUT print $output;
}

Verwenden können Sie dieses Skript z. B. folgendermaßen

RewriteMap dates prg:/Pfad/von/datemap.pl
# Zugriffe auf /news/now in /news/JJJJ-MM-DD umwandeln RewriteRule ^/news/now/(.*) /news/${dates:now}/$1
# Zugriffe auf /news/yesterday umwandeln RewriteRule ^/news/yesterday/(.*) /news/${dates:yesterday}/$1

Noch effizienter wird es, wenn der Teil des Verzeichnispfades hinter /news/ direkt an die Map durchgereicht wird

RewriteRule ^/news/([^/]+)/(.*) /news/${dates:$1}/$2

Unter Windows müssen Sie eine wichtige Änderung durchführen, damit ein solches Map-Skript ausgeführt werden kann: Da ein Perl-Skript formal kein ausführbares Programm ist, können Sie als Quelle Ihres Programms nicht einfach so etwas wie C:/Verzeichnis/skript.pl verwenden, sondern müssen den Pfad des Perl-Interpreters angeben Hier sieht die RewriteMap-Anweisung z. B. so aus

RewriteMap dates \
"prg:C:/Perl/bin/perl.exe C:/Apache2/conf/datemap.pl"

Aber auch mit dieser Option ist auf Windows-Systemen von Map-Programmen abzuraten

  • Besonders die Inkompatibilität mit Zeilenumbrüchen sorgt dafür, dass sie auf dieser Plattform oft hängen bleiben
RewriteLock Lock-Datei zur RewriteMap-Synchronisation

Version 1.3 bis 2.2 Modul mod_rewrite Kontext Server

Syntax RewriteLock Dateipfad Standardwert nicht gesetzt

Wenn Sie selbst geschriebene Programme als RewriteMap verwenden, benötigen Sie eine mithilfe dieser Direktive definierte Lock-Datei

  • Diese sorgt dafür, dass nicht mehrere Anfragen gleichzeitig auf das Programm zugreifen
Beispiel
RewriteLock /var/run/apache2/rewrite.lck

Ab Apache 2.3.4 wird der allgemeine Wert der Direktive Mutex (siehe Kapitel 6, »Grundkonfiguration«) für das Rewrite-Locking verwendet

RewriteOptions

Zusätzliche Rewrite-Optionen

Seit Version 1.3; MaxRedirects seit 2.0.45 und nicht mehr ab 2.1-beta Modul mod_rewrite Kontext Server, <VirtualHost>, <Directory>, <Location>, <Files>, .htaccess (FileInfo) Syntax RewriteOptions Option [Option ...] Standardwert MaxRedirects=10

Diese Direktive ermöglicht es, zusätzliche Rewrite-Optionen zu setzen

  • Folgende zwei Optionen sind möglich
  • inherit Sämtliche Rewrite-Einstellungen wie RewriteRule, RewriteMap usw. werden aus dem übergeordneten Kontext übernommen
  • MaxRedirects=Anzahl Beschränkt die Verarbeitung auf eine maximale Anzahl interner Weiterleitungen, um der Gefahr einer Endlosschleife zu entgehen
  • Wenn die angegebene Anzahl überschritten wird, wird eine Meldung mit dem Status 500 Internal Script Error geliefert
  • Die Voreinstellung ist 10; in den allermeisten Fällen sollte sie ausreichen
  • Seit Apache 2.2 ist diese Option nicht mehr verfügbar

Rewrite-Beispiele Wie Sie gesehen haben, wurden in den Beschreibungen der einzelnen RewriteDirektiven noch keine ausführlichen Beispiele gezeigt

  • Da die Direktiven äußerst komplex sind und vielfältige Optionen besitzen, war es ratsam, sie zunächst im Überblick zu beschreiben

Dafür finden Sie hier eine kleine Sammlung von Beispielen

  • In den späteren Kapiteln dieses Buches wird noch des Öfteren auf mod_rewrite zurückgegriffen, da es praktische Lösungen für zahlreiche Situationen bietet
  • Ein etwas umfangreicheres

»Rewrite-Kochbuch« finden Sie in der Apache-Online-Konfiguration: Der »URL Rewriting Guide« von Ralf S. Engelschall, Autor des Moduls, befindet sich unter der URL http://httpd.apache.org/docs2.2/misc/rewriteguide.html

  • Einfacher Alias Selbstverständlich beherrscht mod_rewrite alle Fähigkeiten von Alias
  • Das folgende Beispiel bindet das Verzeichnis /usr/local/apache2/mydocs unter dem URL-Pfad /text ein
RewriteEngine On RewriteRule ^/text(.*) /usr/local/apache2/mydocs$1

Auch die erweiterten Funktionen von AliasMatch sind natürlich in RewriteRule enthalten – schließlich ist der Vergleichstext ohnehin ein regulärer Ausdruck

  • Dieses Beispiel leitet alle Anfragen nach Dokumenten mit der Endung .htm oder .html auf entsprechende .php-Dateien um (eine nette Spielerei, die die verwendete Technologie für Server-Anwendungen zumindest vordergründig versteckt)
RewriteEngine On RewriteRule ^(.*)\.html?$ $1.php
  • Einfache Weiterleitung Auch Weiterleitungen im Stil von Redirect und RedirectMatch sind mit RewriteRule natürlich überhaupt kein Problem
  • Dazu muss die Direktive mit dem Flag [R] aufgerufen werden

Das folgende Beispiel leitet alle Anfragen auf die Site www.ersatz-server.de weiter; Sie könnten so etwas brauchen, wenn Sie unaufschiebbare Wartungsarbeiten an Ihrem Server durchführen müssen

RewriteEngine On
RewriteRule .* http://www.ersatz-server.de [R]

Das nächste Beispiel leitet dagegen Anfragen, die mit dem Verzeichnis /sales beginnen, an den Server sales.mynet.de weiter – so etwas ist ideal, wenn ein ehemaliges Unterverzeichnis auf einen virtuellen Host oder gar einen eigenen Server-Rechner ausgelagert wird

RewriteEngine On
RewriteRule ^/sales(.*) http://sales.mynet.de$1 [R]
  • Serverseitige Browser-Weiche Wenn Sie schon einmal in JavaScript programmiert haben, kennen Sie sicherlich die berüchtigten Browser-Weichen, die je nach Browser-Modell und -Version unterschiedliche Teile eines Skripts ausführen
  • Wenn Sie für bestimmte Browser völlig separate Seiten anbieten möchten, können Sie das Ganze auch serverseitig erledigen
  • Beispielsweise werden mit den beiden folgenden Konfigurationsanweisungen sämtliche Anfragen von Usern, die den Internet Explorer verwenden, mit ansonsten gleichen Pfad- und Dateiangaben in das Unterverzeichnis /msie umgeleitet
RewriteEngine On RewriteCond %{HTTP_USER_AGENT} msie [NC]
RewriteRule ^/(.*) /msie/$1

Die Server-Variable HTTP_USER_AGENT, die den Wert des Anfrage-Headers UserAgent enthält, wird mit dem regulären Ausdruck msie verglichen – vorsichtshalber mit dem Flag [NC], damit die Groß- und Kleinschreibung nicht beachtet wird

  • Happy Hour Angenommen, ein E-Commerce-Shop möchte seinen Kunden je nach Uhrzeit spezielle Sonderangebote machen, sofern diese sofort bestellt werden

Die folgende Kombination aus RewriteCond und RewriteRule leitet Anfragen für das Dokument /angebot.html auf /happyhour.html um, wenn die Stunde den Wert 19 hat (wenn es also zwischen 19:00 und 19:59 Uhr ist)

RewriteEngine On RewriteCond %{TIME_HOUR} =19
RewriteRule ^/angebot.html$ /happyhour.html

Zu allen anderen Uhrzeiten wird die RewriteRule-Direktive übergangen, weil die Bedingung in der RewriteCond-Anweisung nicht zutrifft

  • »Microsoft-Free Friday«

Unter zahlreichen Adressen im Web können Sie ein Apache-Modul herunterladen, das freitags alle User aussperrt, die den Microsoft Internet Explorer verwenden (suchen Sie mit einer Suchmaschine Ihrer Wahl nach »Microsoft-Free Friday«)

  • Das ist zwar ein nettes Beispiel für die Modulprogrammierung, aber eigentlich überhaupt nicht nötig – mit zwei RewriteCond- und einer RewriteRule-Direktive lässt sich nämlich dasselbe erreichen
RewriteEngine On RewriteCond %{TIME_WDAY} =5
RewriteCond %{HTTP_USER_AGENT} msie [NC]
RewriteRule .* /no-ms.html
  • Session-Tracking Sicher haben Sie schon einmal eine URL wie diese gesehen: http://

www.mynet.de/6FC9387432BA02E4/info.html

  • Die lange Hexadezimalzahl dürfte hier in aller Regel kein echtes Verzeichnis sein, sondern eine SessionID
  • Sie dient dazu, aufeinanderfolgende Anfragen desselben Users verfolgen zu können – dies ist z. B. wichtig, um Bestellinformationen über mehrere Seiten hinweg gespeichert zu halten
  • Es ist praktischer, Session-IDs in den URLPfad zu integrieren, als sie im Query-String zu transportieren
  • Auch das Logging jeder einzelnen Session wird auf diese Weise erleichtert

Die folgende Lösung generiert beim ersten Zugriff auf eine beliebige URL der Website eine neue Session-ID und leitet anschließend jede Anfrage mit Session-ID auf das eigentliche Dokument um, das diese ID natürlich nicht hat Das erste Hilfsmittel ist eine RewriteMap in Form eines kleinen Perl-Skripts, das auf Anfrage eine 16-stellige hexadezimale Zufallszahl produziert

  • Dieses Skript heißt session.pl und sieht so aus
#!/usr/bin/perl -w use strict;
# Autoflush select (STDOUT);
$| = 1;
# Liste mit Hex-Ziffern für die Session-ID my @hexnums = qw (0 1 2 3 4 5 6 7 8 9 A B C D E F);
# Hauptschleife while (<STDIN>) {
# Der Wert des Schlüssels ist egal # es wird auf jeden Fall eine Session-ID erzeugt my $id = ;
for (my $i = 0; $i < 16; $i++) {
$id .= $hexnums [int (rand (16))];
}
# Neue Session-ID ausgeben print "$id\n";
}

Dieses Map-Skript muss nun als RewriteMap registriert werden

  • Dies funktioniert folgendermaßen
RewriteMap session prg:/usr/local/apache2/mytools/session.pl

Den Pfad müssen Sie natürlich anpassen

  • Bei der Beschreibung von RewriteMap wurde bereits erwähnt, dass unter Windows auch der Pfad des Interpreters angegeben werden muss, beispielsweise so
RewriteMap session "prg:C:/Perl/bin/perl.exe \
C:/Apache2/mytools/session.pl"

Allerdings ist die Wahrscheinlichkeit dennoch groß, dass es auf Windows-Systemen trotz alledem nicht funktioniert Als Nächstes müssen Sie dafür sorgen, dass alle Anfrage-URLs, die noch keine Session-ID enthalten, sich eine solche aus dieser RewriteMap besorgen

Dazu dient folgende RewriteRule

RewriteRule !^/[A-Z0-9]{16}/(.*) /${session:id}/$1 [L]

Zu guter Letzt müssen alle Anfragen mit Session-ID auf die entsprechende Ressource ohne ID umgelenkt werden

RewriteRule ^/[A-Z0-9]{16}/(.*) /$1


Anhang

Siehe auch

Dokumentation

Links

Projekt

Weblinks