Serveur Apache HTTP Version 2.4
Ce document compl�te la documentation de r�f�rence du
module mod_rewrite
. Il pr�sente un certain nombre
de techniques avanc�es quant �
l'utilisation de mod_rewrite.
La fragmentation ou "sharding" est une technique courante de distribution de la charge du serveur ou de l'espace de stockage. Quand on utilise cette m�thode, un serveur frontal utilise l'URL pour r�partir de mani�re appropri�e les utilisateurs et objets entre diff�rents serveurs d'arri�re-plan.
On maintient une table de correspondance entre utilisateurs et serveurs cibles dans des fichiers externes. Ces derniers se pr�sentent comme suit :
utilisateur1 serveur_physique_utilisateur1
utilisateur2 serveur_physique_utilisateur2
: :
Tout ceci est enregistr� dans un fichier
correspondances-utilisateurs-serveurs
. Le but est de
faire correspondre
/u/utilisateur1/chemin
avec
http://serveur_physique_utilisateur1/u/utilisateur/chemin
il n'est ainsi pas n�cessaire que tous les chemins URL soient valides sur tous les serveurs physiques d'arri�re-plan. Le jeu de r�gles suivant fait tout ceci pour nous, en s'appuyant sur les fichiers de correspondances, en supposant que serveur0 est un serveur par d�faut qui sera utilis� lorsqu'un utilisateur ne poss�dera pas d'entr�e dans la table de correspondances :
RewriteEngine on RewriteMap users-to-hosts txt:/path/to/map.users-to-hosts RewriteRule ^/u/([^/]+)/?(.*) http://${users-to-hosts:$1|server0}/u/$1/$2
Voir la documentation de RewriteMap
pour une description plus
approfondie de la syntaxe de cette directive.
Nous voulons g�n�rer du contenu de mani�re dynamique, mais le conserver de mani�re statique lorsqu'il a �t� g�n�r�. La r�gle suivante v�rifie l'existence du fichier statique, et le g�n�re s'il est absent. Les fichiers statiques peuvent �tre supprim�s p�riodiquement si on le d�sire (par exemple via cron), et seront r�g�n�r�s � la demande.
# Cet exemple n'est valable que dans un contexte de r�pertoire RewriteCond %{REQUEST_URI} !-U RewriteRule ^(.+)\.html$ /regenerate_page.cgi [PT,L]
L'op�rateur -U
permet de d�terminer si la cha�ne
de test (dans ce cas REQUEST_URI
) est une URL valide.
Pour ce faire, il utilise une sous-requ�te. Si cette sous-requ�te
�choue, ou en d'autres termes, si la ressource demand�e n'existe pas,
cette r�gle invoque le programme CGI
/regenerate_page.cgi
qui g�n�re la ressource
demand�e et la sauvegarde dans le r�pertoire des documents, de
fa�on � ce qu'une copie statique puisse �tre servie lors d'une
demande ult�rieure.
De cette fa�on, les documents qui ne sont pas mis � jour r�guli�rement peuvent �tre servis sous une forme statique. Si ces documents doivent �tre r�actualis�s, on peut les supprimer du r�pertoire des documents, et ils seront ainsi r�g�n�r�s � la prochaine demande.
Nous voulons r�partir la charge de mani�re al�atoire entre plusieurs serveurs en utilisant mod_rewrite.
Pour y parvenir, nous allons utiliser la directive RewriteMap
et une liste de
serveurs.
RewriteEngine on RewriteMap lb rnd:/path/to/serverlist.txt RewriteRule ^/(.*) http://${lb:serveurs}/$1 [P,L]
liste-serveurs.txt
contiendra la liste des serveurs :
## liste-serveurs.txt
serveurs un.example.com|deux.example.com|trois.example.com
Si vous voulez qu'un serveur se voit confier d'avantage de charge que les autres, faites le figurer plusieurs fois dans la liste.
Apache poss�de un module de r�partition de charge -
mod_proxy_balancer
- beaucoup plus souple et pr�sentant
plus de fonctionnalit�s dans ce domaine que mod_rewrite.
Lorsque nous cr�ons une page web complexe, ne serait-il pas souhaitable que le navigateur web actualise automatiquement la page chaque fois que nous en sauvegardons une nouvelle version � partir de notre �diteur ? Impossible ?
Non ! Nous allons pour cela combiner la fonctionnalit� MIME
multipart, la fonctionnalit� NPH du serveur web et la
puissance de mod_rewrite
pour la manipulation
d'URLs. Tout d'abord, nous d�finissons une nouvelle
fonctionnalit� pour les URLs : l'ajout de
:refresh
� toute URL fait que la 'page' est
actualis�e chaque fois que la ressource est mise � jour dans
le syst�me de fichiers.
RewriteRule ^(/[uge]/[^/]+/?.*):refresh /interne/cgi/apache/nph-refresh?f=$
Nous appelons maintenant cette URL
/u/foo/bar/page.html:refresh
ce qui entra�ne en interne l'invocation de l'URL
/interne/cgi/apache/nph-refresh?f=/u/foo/bar/page.html
Il ne reste plus qu'� �crire le script NPH-CGI. Bien que l'on �crive habituellement dans ces cas "laiss� � la charge du lecteur � titre d'exercice", ;-) je vous l'offre, aussi.
#!/sw/bin/perl ## ## nph-refresh -- script NPH/CGI pour l'actualisation automatique de ## pages ## Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved. ## $| = 1; # �clate la variable QUERY_STRING @pairs = split( /&/, $ENV{'QUERY_STRING'} ); foreach $pair (@pairs) { ( $name, $value ) = split( /=/, $pair ); $name =~ tr/A-Z/a-z/; $name = 'QS_' . $name; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; eval "\$$name = \"$value\""; } $QS_s = 1 if ( $QS_s eq '' ); $QS_n = 3600 if ( $QS_n eq '' ); if ( $QS_f eq '' ) { print "HTTP/1.0 200 OK\n"; print "Content-type: text/html\n\n"; print "<b>ERROR</b>: No file given\n"; exit(0); } if ( !-f $QS_f ) { print "HTTP/1.0 200 OK\n"; print "Content-type: text/html\n\n"; print "<b>ERROR</b>: File $QS_f not found\n"; exit(0); } sub print_http_headers_multipart_begin { print "HTTP/1.0 200 OK\n"; $bound = "ThisRandomString12345"; print "Content-type: multipart/x-mixed-replace;boundary=$bound\n"; &print_http_headers_multipart_next; } sub print_http_headers_multipart_next { print "\n--$bound\n"; } sub print_http_headers_multipart_end { print "\n--$bound--\n"; } sub displayhtml { local ($buffer) = @_; $len = length($buffer); print "Content-type: text/html\n"; print "Content-length: $len\n\n"; print $buffer; } sub readfile { local ($file) = @_; local ( *FP, $size, $buffer, $bytes ); ( $x, $x, $x, $x, $x, $x, $x, $size ) = stat($file); $size = sprintf( "%d", $size ); open( FP, "<$file" ); $bytes = sysread( FP, $buffer, $size ); close(FP); return $buffer; } $buffer = &readfile($QS_f); &print_http_headers_multipart_begin; &displayhtml($buffer); sub mystat { local ($file) = $_[0]; local ($time); ( $x, $x, $x, $x, $x, $x, $x, $x, $x, $mtime ) = stat($file); return $mtime; } $mtimeL = &mystat($QS_f); $mtime = $mtime; for ( $n = 0 ; $n & lt ; $QS_n ; $n++ ) { while (1) { $mtime = &mystat($QS_f); if ( $mtime ne $mtimeL ) { $mtimeL = $mtime; sleep(2); $buffer = &readfile($QS_f); &print_http_headers_multipart_next; &displayhtml($buffer); sleep(5); $mtimeL = &mystat($QS_f); last; } sleep($QS_s); } } &print_http_headers_multipart_end; exit(0); ##EOF##
Certains sites avec des milliers d'utilisateurs organisent
les r�pertoires utilisateurs de mani�re structur�e, c'est �
dire que chaque r�pertoire utilisateur se trouve dans un
sous-r�pertoire dont le nom commence (par exemple) par le
premier caract�re du nom de l'utilisateur. Ainsi,
/~larry/chemin
correspond �
/home/l/larry/public_html/chemin
, alors
que /~waldo/chemin
correspond �
/home/w/waldo/public_html/chemin
.
On utilise le jeu de r�gles suivant pour d�velopper les URLs avec tilde selon l'organisation structur�e pr�c�dente.
RewriteEngine on RewriteRule ^/~(([a-z])[a-z0-9]+)(.*) /home/$2/$1/public_html$3
Par d�faut, la redirection vers un ancrage HTML ne fonctionne
pas, car mod_rewrite �chappe le caract�re #
en le
transformant en %23
, ce qui rend la redirection
inop�rante.
On utilise le drapeau [NE]
dans la r�gle
RewriteRule
. NE signifie "No Escape".
Nous voulons servir des contenus diff�rents selon l'heure du jour en utilisant mod_rewrite.
Il existe de nombreuses variables nomm�es
TIME_xxx
utilisables dans les conditions de
r��criture. Utilis�es en conjonction avec les mod�les de
comparaison lexicographique sp�ciaux <STRING
,
>STRING
et =STRING
, elles
permettent d'effectuer des redirections d�pendant de
l'heure :
+RewriteEngine on +RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700 +RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900 +RewriteRule ^foo\.html$ foo.day.html [L]
Avec cet exemple, l'URL foo.html
renvoie
le contenu de foo.jour.html
durant le
cr�neau horaire 07:01-18:59
, et le contenu de
foo.nuit.html
le reste du temps.
mod_cache
, les mandataires
interm�diaires et les navigateurs peuvent chacun mettre en cache
les r�ponses et ainsi afficher une des deux pages en dehors de
la fen�tre de temps configur�e. On peut utiliser
mod_expires
pour contourner ce probl�me. Il est
cependant bien plus commode de servir un contenu dynamique, et
de le personnaliser en fonction de l'heure du jour.Ici, nous voulons conserver une certaine forme de statut lorsqu'une r��criture a eu lieu. Par exemple, vous souhaitez consigner le fait que cette r��criture a eu lieu, et vous servir plus tard de cette information pour d�terminer si une requ�te sera concern�e par cette r��criture. Pour y parvenir, on peut utiliser une variable d'environnement.
Utiliser le drapeau [E] pour d�finir une variable d'environnement.
RewriteEngine on RewriteRule ^/cheval/(.*) /poney/$1 [E=rewritten:1]
Plus loin dans votre jeu de r�gles, vous pouvez v�rifier le contenu de cette variable d'environnement via une directive RewriteCond :
RewriteCond %{ENV:rewritten} =1