<-
Apache > Serveur HTTP > Documentation > Version 2.4 > Rewrite

Advanced Techniques with mod_rewrite

Langues Disponibles:  en  |  fr 

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.

Notez que la plupart des exemples ne fonctionneront pas en l'�tat dans la configuration particuli�re de votre serveur ; il est donc important de bien comprendre leur fonctionnement, plut�t que de simplement les copier/coller dans votre configuration.

Voir aussi

top

Distribution de la charge entre plusieurs serveurs d'arri�re-plan en fonction de l'adresse IP

Description :

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.

Solution :

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.

top

R�g�neration de contenu � la vol�e

Description :

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.

Solution :
A cet effet, on utilise le jeu de r�gles suivant :
# 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.

top

R�partition de charge

Description :

Nous voulons r�partir la charge de mani�re al�atoire entre plusieurs serveurs en utilisant mod_rewrite.

Solution :

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.

Discussion

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.

top

Actualisation automatique d'un document

Description :

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 ?

Solution :

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##
top

R�pertoires Home structur�s

Description :

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.

Solution :

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
top

Redirection des ancrages

Description :

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.

Solution :

On utilise le drapeau [NE] dans la r�gle RewriteRule. NE signifie "No Escape".

Discussion :
Cette technique fonctionne bien entendu pour tout autre caract�re sp�cial que mod_rewrite, par d�faut, code pour insertion dans une URL.
top

R��criture d�pendant de l'heure

Description :

Nous voulons servir des contenus diff�rents selon l'heure du jour en utilisant mod_rewrite.

Solution :

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

D�finir des variables d'environnement en fonction de certaines parties de l'URL

Description :

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.

Solution :

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

Langues Disponibles:  en  |  fr 

top

Commentaires

Notice:
This is not a Q&A section. Comments placed here should be pointed towards suggestions on improving the documentation or server, and may be removed again by our moderators if they are either implemented or considered invalid/off-topic. Questions on how to manage the Apache HTTP Server should be directed at either our IRC channel, #httpd, on Freenode, or sent to our mailing lists.