6.9.2. Definition von Regeln
Die Verarbeitung der Regeln erfolgt nach dem folgenden Verfahren:

  • Das Modul geht alle RewriteRule nacheinander durch.
  • Wenn eine RewriteRule passt, schaut es die davor befindlichen RewriteCond-Direktiven durch.
  • Die RewriteCond-Bedingungen werden der Reihe nach bewertet.
  • Sobald die erste RewriteCond fehl schlägt, wird mit der nächsten RewriteRule weiter gemacht.
  • Sofern alle RewriteCond zutreffen (oder wenn keine vorhanden sind) wird der Rewrite der Rule gestartet.

Bei den RewriteRules wird erst der "Match" gegen die URL durchgeführt. Bei den RewriteConds werden erst alle Variablen ersetzt und wenn alle Daten vollständig sind, wird die Bewertung vorgenommen.
6.9.2.1. Regel
Die RewriteRule besteht aus zwei Teilen. Zum einen einem "Pattern" (Muster), das die URLs begrenzt, die umgeschrieben werden sollen und zum anderen die Transformation, die auf diese URL durchgeführt werden soll:

          RewriteRule  PATTERN     SUBSTITUTION  [FLAGS]

Als Grundlage für das PATTERN (und auch die Substitution) dient die Syntax, die auch bei den Regexp von Perl Eingang gehalten hat. Ein Kurzüberblick:

     
Symbol
Beschreibung
.
ein einzelnes Zeichen
[chars]
die Menge der Zeichen "chars"
[^chars]
keines der Zeichen chars
text1|text2
Alternative: text1 oder text2
?
0 oder 1mal das Vorhergehende
*
0 oder n-mal das Vorhergehende
+
1 oder n-mal das Vorhergehende
()
Gruppierung von Text (kann als "backreference" dienen - $1 = erste Klammer usw.)
^
Ausrichtung am Anfang der Zeile
$
Ende der Zeile
\char
"Escaping" von Sonderzeichen (z.B. .[]()...)

Zusätzlich unterstützt das mod_rewrite das "!" als "nicht" - sprich Regeln können logisch umgekehrt werden.

Backreferences erlaube es, Ausdrücke, die in Klammern stehen, an späterer Stelle wieder zu referenzieren und einzufügen. Dabei sind $N (N=0..9) Referenzen auf RewriteRule und %N Referenzen auf RewriteCond- Ausdrücke. Servervariablen können mit %{VARNAME} angesprochen werden, Einträge in Hashes (Maps, DB usw.) mit ${mapname:KEY|default} und Umgebungsvariablen mit %{ENV:VAR}

Soll nur eine Regel definiert werden, aber (noch) kein Rewrite durchgeführt werden, kann für die Substitution auch ein "-" stehen.

Optional kann man nach der Substition auch noch zusätzliche Flags in eckigen Klammern als drittes Argument angeben. Die Flags werden per Kommata getrennt.

Flag
Beschreibung
Beispiel
redirect|R [=code]
Erzwinge einen Redirect. Es wird eine vollständige URI erzeugt und dem Browser ein Redirect gesendet.
[R]
[R=303]
forbidden|F
Erzeuge ein HTTP-Code 403 (Forbidden)
[F]
gone|G
Sende einen HTTP-Code 410 (Gone)
[G]
proxy|P
Schließe die aktuelle Regel ab und übergibt die Anfrage sofort an das Apache-Proxy- Modul weiter. Die Abarbeitung des Rewrites wird abgebrochen
[P]
last|L
Breche nach der aktuellen Regel die weitere Prüfung der RewriteRegel ab (last Rule)
[L]
next|N
Beginne die RewriteRule noch einmal von vorne (Achtung: Endlosschleifengefahr)
[N]
chain|C
"Chain"-Rules, d.h. bearbeite die aktuelle Regel und wenn die Regel erfolgreich war, nimm auch die nächste Regel - sonst überspringe sie
[C]
type|T=MIME-TYPE
Erzwinge den MIME-TYPE für das Ergebnis und triggere damit u.U. auch andere Module
[T=application/x-httpd-cgi]
nosubreq|NS
Übergehe die Regel, wenn die URL durch einen internes Modul erzeugt wurde (z.B. mod_include oder mod_alias)
[NS]
nocase|NC
Das PATTERN ist unabhängig von der Groß- und Kleinschreibung.
[NC]
qsappend|QSA
füge den Query-String in der Substitution an - ersetzte ihn nicht
[QSA]
noescape|NE
Die URL soll nicht encoded werden und vorhandene URL-Codes werden decoded
/abc/(.*)    /cde?arg=P1\%3d$1 [R,NE]
d.h.: /abc/xyz -> /cde?arg=P1=abc
skip|S=NUM
überspringe die nächsten NUM-Regeln
[S=10]
env|E=VAR:VAL
Belege die Umgebungsvariable VAR mit dem Wert VAL
[E=VAR1=42]
cookie|CO=NAME:VAL:domain[:lifetime[:path]]
Setze das Cookie NAME. VAL ist der Wert, Domain die Domain des Cookies, die Lebenzeit und der Pfad ist der Pfad des Cookies.
[CO=test:42:test.de]

Einige Beispiele für die Anfrage "GET /somepath/pathinfo" (globale Regeln):

Regel
Ergebnis
^/somepath(.*)      otherpath$1
ungültig (wäre nur per Directory sinnvoll)
^/somepath(.*)      otherpath$1  [R]
ungültig (wäre nur per Directory sinnvoll)
^/somepath(.*)      otherpath$1  [P]
ungültig (wäre nur per Directory sinnvoll)
^/somepath(.*)      /otherpath$1
/otherpath/pathinfo
^/somepath(.*)      /otherpath$1  [R]
http://thishost/otherpath/pathinfo (ext. Redirect)
^/somepath(.*)      /otherpath$1  [P]
unsinnig
^/somepath(.*)      http://thishost/otherpath$1
/otherpath/pathinfo
^/somepath(.*)      http://thishost/otherpath$1  [R]
http://thishost/otherpath/pathinfo (ext. Redirect)
^/somepath(.*)      http://thishost/otherpath$1  [P]
unsinnig
^/somepath(.*)      http://otherhost/otherpath$1
http://otherhost/otherpath/pathinfo  (ext. Redirect)
^/somepath(.*)      http://otherhost/otherpath$1 [R]
http://otherhost/otherpath/pathinfo  (ext. Redirect)
^/somepath(.*)      http://otherhost/otherpath$1 [P]
http://otherhost/otherpath/pathinfo  (Proxy)


Einige Beispiele für die Anfrage "GET /somepath/localpath/pathinfo" für den Directory-Container "<Directory /somepath>":


Regel
Ergebnis
^localpath(.*)      otherpath$1
/somepath/otherpath/pathinfo
^localpath(.*)      otherpath$1 [R]
http://thishost/somepath/otherpath/pathinfo (ext Redirect)
^localpath(.*)      otherpath$1 [P]
unsinnig
^localpath(.*)      /otherpath$1
/otherpath/pathinfo
^localpath(.*)      /otherpath$1 [R]
http://thishost/otherpath/pathinfo
^localpath(.*)      /otherpath$1 [P]
unsinnig
^localpath(.*)      http://thishost/otherpath$1
/otherpath/pathinfo
^localpath(.*)      http://thishost/otherpath$1 [R]
http://thishost/otherpath/pathinfo (ext. Redirect)
^localpath(.*)      http://thishost/otherpath$1 [P]
unsinnig
^localpath(.*)      http://otherhost/otherpath$1
http://otherhost/otherpath/pathinfo (ext. Redirect)
^localpath(.*)      http://otherhost/otherpath$1 [R]
http://otherhost/otherpath/pathinfo (ext. Redirect)
^localpath(.*)      http://otherhost/otherpath$1 [P]
http://otherhost/otherpath/pathinfo (Proxy)



6.9.2.2. Bedingung
Die RewriteCond legt fest, unter welchen Bedingungen eine Substitution erfolgen soll. Die Syntax lautet:

          RewriteCond      TESTSTRING           CONDPATTERN     [FLAG]

Eine oder mehrere RewriteCond können einer RewriteRule voraus gehen. Die Regel wird dann nur abgearbeitet, wenn alle Bedingungen gültig sind. Der Teststring gibt an, was getestet werden soll (URL, Servervariable, Umgebungsvariable, ...) und das Conditionpattern den Test, der durchgeführt wird. Auch bei den Bedingungen kann ein optionales FLAG folgen.

Der Teststring kann aus den folgenden Komponenten bestehen:

Komponente
Beschreibung
plain Text
Zeichen
$N  (1<=N <=9)
Backreference auf RewriteRule-Felder
%N (1<=N <=9)
Backreference auf RewriteCond-Felder
${mapname:key|default}
Ausdrücke aus einem Hash
%{Variable}
Server-Variablen (z.B. aus SetEnvIf oder CGI-Schnittstelle)
%{ENV:Variable}
Umgebungsvariable
%{HTTP:Header}
HTTP-Header-Wert (z.B.  %{HTTP:Proxy-Connection})
%{LA-U:variable}
"look ahead" - schaue, welchen Wert die Variable am Ende haben wird... z.B. %{LA-U:REMOTE_USER}, da dieser erst später ermittelt wird.

Das CondPattern ist ein Perl-Regexp, der auf den Test-String angewendet wird. Der Umfang des Perl-Regexp wird im folgenden erweitert:

    • "!" steht für "nicht"  
    • "<" steht für kleiner (String-Vergleich)
    • ">" steht für kleiner (String-Vergleich)
    • "=" steht für gleich (String-Vergleich)
    • "-d" der Teststring ist ein Directory
    • "-f"  der Teststring ist ein reguläres File
    • "-s" der Teststring ist ein reguläres nicht leeres File
    • "-l"  der Teststring ist ein Link
    • "-F" der Teststring ist ein reguläres File und prüft, ob es für den Server erreichbar ist (Subrequest)
    • "-U" der Teststring ist eine reguläre URL und erreichbar (Subrequest)

Für die optionalen Flags sind folgende Werte möglich (wieder per Kommata trennbar):

Flag
Beschreibung
Beispiel
nocase|NC
Der Test ist unabhängig von der Groß- und Kleinschreibung.
[NC]
ornext|OR
diese und die nächste RewriteCond sind per ODER verknüpft
RewriteCond %{REMOTE_HOST}  ^host1.*  [OR]
RewriteCond %{REMOTE_HOST}  ^host2.*  [OR]
RewriteCond %{REMOTE_HOST}  ^host3.*
RewriteRule ...
per Default gilt ein AND
RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
RewriteRule  ^/$                 /homepage.max.html  [L]

RewriteCond  %{HTTP_USER_AGENT}  ^Lynx.*
RewriteRule  ^/$                 /homepage.min.html  [L]

RewriteRule  ^/$                 /homepage.std.html  [L]

6.9.2.3. Maps
Die RewriteMap kommt zum Einsatz, wenn man eine größere Menge von Begriffen durch andere ersetzen möchte. Ein Beispiel wäre, die Ersetzung der Login-Username durch Vor- und Zuname. Die entsprechende Direktive lautet:

          RewriteMap   MapName          MapType:MapSource

Die Map ist vergleichbar unter Perl mit einem Assoziativen Array (Hash). Nachdem die Map definiert ist, können die einzelnen Felder mit den Variablen

     ${ MapName : LookupKey }
     ${ MapName : LookupKey | DefaultValue }

aufgelöst werden.

Für die Felder MapType:MapSource sind folgende Kombinationen möglich:

MapType
MapSource
Beschreibung
Beispiel Anweisung
Beispiel-Datei
txt
/pfad/zur/datei
plain ASCII, Leerzeilen, Kommentare '#', oder Wertepaare durch Whitespace getrennt
RewriteMap real-to-user txt:/path/to/file/map.txt
# map.txt
Nepumuk                nn     #    Nepomuk Niespriem
SchlafSchlumpf       ss    
rnd
/pfad/zur/datei
wie txt, nur mehrere Werte möglich, die zufällig ausgewählt werden.
RewriteMap servers rnd:/path/to/file/map.txt
# map.txt (rnd)
static   www1|www2|www3|www4
dynamic  www5|www6
dbm
/pfad/zur/datei
die Daten werden in einer Unix-DBM- Datei abgelegt. Der Typ der DBM hängt von der Compilierung ab
RewriteMap real-to-user dbm:/path/to/file/map.db
Script zur Umwandlung txt2dbm:
#!/path/to/bin/perl
##
##  txt2dbm -- convert txt map to dbm format
##

use NDBM_File;
use Fcntl;

($txtmap, $dbmmap) = @ARGV;

open(TXT, "<$txtmap") or die "Couldn't open $txtmap!\n";
tie (%DB, 'NDBM_File', $dbmmap,O_RDWR|O_TRUNC|O_CREAT, 0644)
  or die "Couldn't create $dbmmap!\n";

while (<TXT>) {
  next if (/^\s*#/ or /^\s*$/);
  $DB{$1} = $2 if (/^\s*(\S+)\s+(\S+)/);
}

untie %DB;
close(TXT);
int
Apache-Funktion
Interne Funktion: toupper, tolower, escape, unescape
RewriteMap small_user int:tolower
 
prg
/path/to/prog
Externes Programm zur Umwandlung. Erhält als Aufrufparameter den Key, Rückgabewert muss ein mit newline- terminierter String oder NULL sein.
RewriteMap lookup_user  prg:/path/to/userlookup.pl
#!/usr/bin/perl
$| = 1;
while (<STDIN>) {
    # ...put here any transformations or lookups...
    print $_;
}


Ein Beispiel:

                    Rewrite von        / Language /~ Realname /.../ File
                    nach                  /u/ Username /.../ File . Language

RewriteLog   /path/to/file/rewrite.log
RewriteMap   real-to-user               txt:/path/to/file/map.txt
RewriteRule  ^/([^/]+)/~([^/]+)/(.*)$   /u/${real-to-user:$2|nobody}/$3.$1
6.9.2.4. RewriteBase
In einem Directory-Container wird normalerweise das entsprechende Directory als Ausgangspunkt für den Rewrite genommen. Dies ist nicht immer sinnvoll (vor allem, wenn hinterher weitere Aliase o.ä. eingesetzt werden). Der Ausgangspunkt kann mit der Direktive

          RewriteBase URL-path

explizit festgelegt werden. Ein Beispiel:

          ...
Alias /xyz    /abc/def
...
<Directory /abc/def>
RewriteEngine On
RewriteBase   /xyz
RewriteRule   ^oldstuff\.html$  newstuff.html  
</Directory>

D.h. die Anfrage /xyz/oldstuff.html wird im Endeffekt zu /abc/def/newstuff.html. Die interne Verabreitung ist wie folgt:

/xyz/oldstuff.html     -> /abc/def/oldstuff.html     (per-server Alias)
/abc/def/oldstuff.html -> /abc/def/newstuff.html  (per-dir    RewriteRule)
/abc/def/newstuff.html -> /xyz/newstuff.html      (per-dir    RewriteBase)

/xyz/newstuff.html     -> /abc/def/newstuff.html  (per-server Alias)

ohne RewriteBase hätte die Regel nicht gegriffen.