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

Quand ne pas utiliser mod_rewrite

Langues Disponibles:  de  |  en  |  es  |  fr  |  ja  |  ko  |  tr  |  zh-cn 

Ce document est un complément à la Documentation de référence de mod_rewrite. Il décrit peut-être un des concepts les plus importants à propos de mod_rewrite - à savoir, quand doit-on éviter de l'utiliser.

mod_rewrite doit être considéré comme un dernier recours, lorsqu'aucune alternative n'est possible. Utiliser mod_rewrite lorsqu'il existe des alternatives plus simples conduit à des configurations confuses, fragiles, et difficiles à maintenir. La compréhension des autres alternatives disponibles est une étape très importante sur le chemin de la maîtrise de mod_rewrite.

Vous devez vous attacher à comprendre le fonctionnement des exemples, car la plupart d'entre eux ne fonctionneront pas sur votre système si vous vous contentez de les copier/coller dans vos fichiers de configuration.

Le cas le plus courant dans lequel mod_rewrite est l'outil approprié est la situation où la seule solution envisageable nécessite l'accès aux fichiers de configuration du serveur, alors que cet accès ne vous est pas accordé. Certaines directives de configuration ne sont disponibles que dans le fichier de configuration du serveur. Si vous ne pouvez agir que sur les fichiers .htaccess, vous devrez donc vous tourner vers mod_rewrite.

Voir aussi

top

Redirection simple

mod_alias fournit les directives Redirect et RedirectMatch qui permettent de rediriger une URL vers une autre. Plutôt que d'utiliser la directive RewriteRule pour ce genre de redirection simple d'une URL ou d'une classe d'URLs vers une autre, on préfèrera l'utilisation de ces directives. En outre, avec RedirectMatch, vous pouvez inclure une expression rationnelle dans votre critère de redirection, ce qui vous permet de bénéficier de nombreux avantages de la directive RewriteRule.

Une utilisation courante de la directive RewriteRule est la redirection de toute une classe d'URLs. Par exemple, toutes les URLs faisant référence au répertoire /un doivent être redirigées vers http://un.example.com/, ou toutes les requêtes http doivent être redirigées vers https.

Pour ce faire, il est préférable d'utiliser la directive Redirect. Souvenez-vous que la directive Redirect conserve les informations relatives au chemin. En d'autres termes, la redirection d'une URL /un va aussi rediriger toutes les URLs de niveaux inférieurs comme /un/deux.html et /un/trois/quatre.html.

Pour rediriger les URLs sous /un vers http://un.example.com/, utilisez cette définition :

Redirect "/one/" "http://one.example.com/"

Pour rediriger un nom d'hôte vers un autre nom d'hôte, par exemple example.com vers www.example.com, voir la méthode Noms d'hôtes canoniques.

Pour rediriger les URLs http vers https, une directive Redirect dans un serveur virtuel HTTP dédié est l’approche la plus propre. Voir la recette Forcer HTTPS pour la configuration recommandée et l’alternative de mod_rewrite pour l’utilisation des fichiers .htaccess.

Ordre de traitement

Si vous mélangez des directives Redirect et RewriteRule dans le même contexte, sachez que leur ordre d’exécution dépend de l’emplacement où elles apparaissent. Dans un contexte de serveur virtuel ou global, c’est mod_rewrite qui agit en premier, alors que dans un contexte de répertoire (fichiers .htaccess), c’est mod_alias. Voir Ordre de traitement des modules pour les détails.

top

Alias d'URL

La directive Alias permet de mettre en correspondance un chemin d’URL avec un répertoire, ce dernier étant en général situé en dehors de l'arborescence définie par la directive DocumentRoot. Bien qu'il soit possible d'effectuer cette mise en correspondance avec mod_rewrite, il est préférable d'utiliser la directive Alias pour des raisons de simplicité et de performances.

Utilisation de la directive Alias

Alias "/cats" "/var/www/virtualhosts/felines/htdocs"

Pour effectuer cette mise en correspondance, mod_rewrite s'impose si vous n'avez pas accès aux fichiers de configuration du serveur. En effet, la directive Alias ne peut pas être utilisée dans un fichier .htaccess, mais seulement dans un contexte de serveur principal ou de serveur virtuel.

En outre, vous pouvez arriver au même résultat avec les liens symboliques, pourvu que Options FollowSymLinks soit activé sur votre serveur.

top

Mandat simple

La directive RewriteRule fournit le drapeau [P] qui permet de faire passer les URIs réécrits par mod_proxy.

RewriteRule "^/?images(.*)" "http://serveur-images.local/images$1" [P]

Cependant, dans les nombreux cas où aucune correspondance au modèle n'est vraiment nécessaire, comme dans l'exemple ci-dessus, il est préférable d'utiliser la directive ProxyPass. L'exemple précédent pourrait être remplacé par :

ProxyPass "/images/" "http://serveur-images.local/images/"

Que vous utilisiez RewriteRule ou ProxyPass, vous devrez dans tous les cas utiliser aussi la directive ProxyPassReverse pour intercepter les redirections en provenance du serveur d'arrière-plan :

ProxyPassReverse "/images/" "http://serveur-images.local/images/"

Vous devrez cependant tout de même utiliser RewriteRule lorsque d'autres RewriteRules se trouvent dans la même portée, car elles agissent en général avant les directives ProxyPass, et peuvent ainsi les court-circuiter.

RewriteRule s’avère vraiment utile pour ne mandater les requêtes que si le contenu n’existe pas localement — par exemple, lors de la migration d’un serveur vers un autre :

RewriteCond "%{REQUEST_FILENAME}"       !-f
RewriteCond "%{REQUEST_FILENAME}"       !-d
RewriteRule "^/(.*)"                    "http://old.example.com/$1" [P]
ProxyPassReverse "/" "http://old.example.com/"

Dans cet exemple, les requêtes pour des ressources qui n’ont pas encore été migrées sont mandatées silencieusement vers l’ancien serveur. Lors de la migration du contenu, les fichiers locaux ont la priorité. N’oubliez pas de toujours inclure une directive ProxyPassReverse pour être sûr que toute redirection effectuée par le serveur dorsal est correctement transmise au client.

top

Test de variables d'environnement

mod_rewrite est souvent utilisé pour effectuer une action en fonction de la présence ou de l'absence d'une variable d'environnement particulière ou d'un en-tête de requête, ce qui peut être accompli de manière plus efficace via la directive <If>.

Considérons par exemple le scénario courant où la directive RewriteRule est utilisée pour forcer un nom d'hôte canonique, tel que www.example.com au lieu de example.com. Il est possible d'utiliser à la place la directive <If> comme suit :

<If "req('Host') != 'www.example.com'">
    Redirect "/" "http://www.example.com/"
</If>

On peut utiliser cette technique dans de nombreux scénarios courant pour remplacer mod_rewrite pour effectuer des actions en fonction d'en-têtes de requêtes ou de réponses, ou de variables d'environnement.

Voir en particulier la documentation sur l'évaluation des expressions pour une vue d'ensemble des types d'expressions que vous pouvez utiliser dans les sections <If>, ainsi que dans certaines directives.

top

Contrôleur frontal / Routage des ressources

Une utilisation très courante de mod_rewrite consiste à router toutes les requêtes pour des ressources non existantes vers un seul script de contrôle frontal (par exemple index.php). Il s’agit de la base du routage dans le cadre de la plus grande partie du web moderne.

L’approche typique avec mod_rewrite est :

RewriteEngine On
RewriteCond "%{REQUEST_FILENAME}" !-f
RewriteCond "%{REQUEST_FILENAME}" !-d
RewriteRule "^(.*)$" "/index.php" [L]

Cette opération peut être effectuée beaucoup plus simplement avec la directive FallbackResource :

FallbackResource /index.php

La directive FallbackResource fait la même chose — les requêtes pour des fichiers et répertoires existants sont traitées normalement, toutes les autres étant routées vers la ressource spécifiée — mais sans la surcharge de travail et la complexité du moteur de réécriture. Elle fonctionne dans les deux contextes de configuration globale du serveur et des fichiers .htaccess.

Pour désactiver une FallbackResource définie dans un répertoire parent :

FallbackResource disabled
top

Configuration conditionnelle avec des expressions rationnelles

Dans de nombreux cas, l’utilisation de RewriteCond peut être remplacée par la directive <If> qui prend en charge une syntaxe des expressions riche et s’intègre parfaitement avec les autres directives de httpd.

Redirection basée sur un élément de la chaîne de paramètres :

<If "%{QUERY_STRING} =~ /lang=fr/">
    Redirect "/welcome" "/bienvenue"
</If>

Restriction d’accès en fonction de la méthode de la requête :

<If "%{REQUEST_METHOD} IN {'DELETE', 'PUT', 'PATCH'}">
    Require ip 10.0.0.0/8
</If>

Blocage des requêtes qui ne comportent pas d’en-tête Host (clients HTTP/1.0) :

<If "-z req('Host')">
    Require all denied
</If>

Voir la documentation sur l’évaluation des expressions pour une description complète de la syntaxe disponible dans les blocs <If>.

top

Blocage du référencement à chaud (Hotlinking) d'images

Description :

Le référencement à chaud consiste pour les autres sites à inclure directement vos images dans leurs pages en utilisant votre bande passante pour servir des contenus pour le site de quelqu'un d'autre. Vous pouvez empêcher cela sans utiliser mod_rewrite.

Solution :

Utilisez la directive SetEnvIf avec la directive Require :

SetEnvIf Referer example\.com localreferer
<FilesMatch "\.(jpg|png|gif)$">
    Require env localreferer
</FilesMatch>
Discussion :

Si vous avez besoin d’une logique plus complexe — comme servir une autre image aux référenceurs à chaud au lieu de rejeter la requête — vous aurez peut-être besoin de mod_rewrite. Les exemples suivants s’appuient sur l’en-tête HTTP_REFERER qui est facultatif et peut être usurpé. La condition !^$ autorise les requêtes qui ne comportent aucun en-tête Referer, de sorte que les utilisateurs qui saisissent l’URL directement, ou dont les navigateurs suppriment cet en-tête ne soient pas bloqués.

Rejeter purement et simplement la requête :

RewriteCond "%{HTTP_REFERER}"  "!^$"
RewriteCond "%{HTTP_REFERER}"  "!www.example.com" [NC]
RewriteRule "\.(gif|jpg|png)$" "-"                [F,NC]

Servir une image alternative :

RewriteCond "%{HTTP_REFERER}"  "!^$"
RewriteCond "%{HTTP_REFERER}"  "!www.example.com"      [NC]
RewriteRule "\.(gif|jpg|png)$" "/images/go-away.png"   [R,NC]
top

Blocage des robots

Description :

Vous voulez bloquer les requêtes persistantes d’un robot particulier ou d’un agent utilisateur qui ignore votre /robots.txt.

Solution :

Utilisez la directive SetEnvIfNoCase avec la directive Require :

SetEnvIfNoCase User-Agent ^NameOfBadRobot goaway
<Location "/secret/files">
    <RequireAll>
        Require all granted
        Require not env goaway
    </RequireAll>
</Location>
Discussion :

Toute technique qui s’appuie sur la chaîne USER_AGENT peut être facilement contournée, car cette chaîne peut être modifiée par le client. Si vous subissez une attaque soutenue, vous devez la traiter à un niveau supérieur, par exemple au niveau de votre pare-feu.

Si vous devez combiner la recherche de correspondance par agent utilisateur et par adresse IP, mod_rewrite peut être utilisé en remplacement :

RewriteCond "%{HTTP_USER_AGENT}"   "^NameOfBadRobot"
RewriteCond "%{REMOTE_ADDR}"       "=123\.45\.67\.[8-9]"
RewriteRule "^/secret/files/"      "-"                   [F]
top

Interdire des hôtes dans une liste de rejets

Description :

Nous souhaitons établir une liste des hôtes auxquels nous voulons interdire l’accès à notre serveur.

Solution :

Pour un simple blocage basé sur l’adresse IP, utilisez la directive Require directement :

<Location "/">
    Require all granted
    Require not ip 193.102.180.41
    Require not ip 192.76.162.40
</Location>
Discussion :

Si vous avez besoin d’une liste d’interdiction dynamique basée sur un fichier (plutôt que d’énumérer des adresses IP dans la configuration), vous pouvez utiliser mod_rewrite et sa directive RewriteMap :

RewriteEngine on
RewriteMap    hosts-deny  "txt:/path/to/hosts.deny"
RewriteCond   "${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND}" "!=NOT-FOUND" [OR]
RewriteCond   "${hosts-deny:%{REMOTE_HOST}|NOT-FOUND}" "!=NOT-FOUND"
RewriteRule   "^"                                      "-"           [F]

Le fichier de mappage contient une entrée par ligne, avec une adresse IP ou un nom d’hôte comme clé et une valeur factice (parce que la directive RewriteMap requiert des paires clé/valeur) :

## hosts.deny
193.102.180.41 -
192.76.162.40 -

La seconde directive RewriteCond présuppose que HostnameLookups est activé. Dans le cas contraire, supprimer-la, ainsi que le drapeau [OR] de la première condition.

top

Serveurs virtuels

Bien qu’il soit possible de gérer les serveurs virtuels avec mod_rewrite, il s’agit rarement de la bonne méthode. Le bon choix consiste pratiquement toujours à créer des blocs <VirtualHost> individuels. Si vous devez gérer un très grand nombre de serveurs virtuels, choisissez plutôt d’utiliser mod_vhost_alias pour créer ces hôtes automatiquement.

Des modules tels que mod_macro permettent aussi de créer un grand nombre de serveurs virtuels dynamiquement.

Utiliser mod_rewrite pour la création de serveurs virtuels peut convenir si vous utilisez un service d’hébergement qui ne vous permet pas d’accéder aux fichiers de configuration du serveur, et que vous soyez par conséquent contraint d’utiliser des fichiers .htaccess.

Voir le document les serveurs virtuels avec mod_rewrite pour plus de détails sur la manière de procéder si cette approche vous semble encore être la bonne.

top

Répartition de charge

Description :

Nous souhaitons répartir la charge entre plusieurs serveurs dorsaux.

Solution :

Utilisez le module mod_proxy_balancer qui fournit une solution de répartition de charge flexible et totalement fonctionnelle. Il prend en charge plusieurs algorithmes de répartition, la persistance de session, les contrôles de bon fonctionnement et une configuration dynamique avec le gestionnaire de répartition de charge (Balancer Manager) — toutes choses impossibles avec l’approche de mod_rewrite.

<Proxy "balancer://mycluster">
    BalancerMember "http://one.example.com"
    BalancerMember "http://two.example.com"
    BalancerMember "http://three.example.com"
</Proxy>
ProxyPass        "/"  "balancer://mycluster/"
ProxyPassReverse "/"  "balancer://mycluster/"
Discussion :

Il est possible de mettre en Ĺ“uvre une répartition de charge aléatoire rudimentaire en utilisant mod_rewrite et une directive RewriteMap de type rnd :

RewriteEngine on
RewriteMap  lb       "rnd:/path/to/serverlist.txt"
RewriteRule "^/(.*)" "http://${lb:servers}/$1"     [P,L]

mod_proxy_balancer est cependant beaucoup plus flexible et fonctionnel que tout ce que vous pourrez « bricoler » en utilisant mod_rewrite, et correspond à l’approche recommandée.

Langues Disponibles:  de  |  en  |  es  |  fr  |  ja  |  ko  |  tr  |  zh-cn