FAQ du serveur HTTP ApacheConsultez toutes les FAQ

Nombre d'auteurs : 9, nombre de questions : 47, dernière mise à jour : 2 septembre 2018 

 
OuvrirSommaireModulesLa réécriture d'URL (URL Rewriting)

Une première idée pourrait nous pousser à utiliser le fichier .htaccess pour rediriger l'internaute à l'aide d'une page 404 de notre choix (la page par défaut pour les URIs non valides). Ce script peut récupérer l'adresse que notre internaute a demandée et utiliser un tableau ou une base de données pour déterminer la véritable page à charger. Cependant, cette approche est incorrecte car Apache envoie une erreur HTTP 404 au navigateur, ce qui empêche le référencement correct de la page Web. Par conséquent, aucune page de votre site ne serait référencée par les moteurs de recherche. La véritable solution implique la réécriture de liens. Il faut pouvoir activer la directive "RewriteEngine" de votre fichier .htaccess de manière à y inclure cette première ligne :

 
Sélectionnez

RewriteEngine on

À partir de là, vous pouvez utiliser la directive RewriteRule dans ce même fichier, conjointement à des expressions régulières. Imaginons par exemple un site fondé sur des articles, sur le principe de : articles.php?article=X (où X est l'identifiant numérique entier de l'article).
Nous aurions une série d'articles de la sorte : articles.php?article=1, articles.php?article=43, articles.php?article=99, etc.
Nous désirons utiliser une arborescence virtuelle au lieu de ces paramètres barbares. Nous aimerions quelque chose comme : articles/titre/X/ Voici comment nous pouvons nous y prendre : il suffit d'afficher les liens de la manière souhaitée dans le HTML et, dans le .htaccess, d'ajouter cette ligne :

 
Sélectionnez

RewriteRule articles/.*/([0-9]+)$ /articles.php?article=$1 [L]

C'est une solution assez complexe, mais elle est détaillée dans le tutoriel de réécriture de liens (URL Rewriting)

Créé le 17 décembre 2008  par Yogui

Lien : Tutoriel de réécriture de liens (URL Rewriting), par Guillaume Rossolini

Voici la liste des conditions à réunir pour être en mesure de tirer profit de la fonction de réécriture d'URL :

  1. Le module mod_rewrite, quelle que soit sa forme - statique ou dynamique (par une directive LoadModule et AddModule dans le cas des versions 1.2 et 1.3), doit être activé.

  2. Rendre ponctuellement (pour un hôte virtuel, depuis un répertoire, etc) actif le moteur de réécriture pour ses besoins à l'aide de :

     
    Sélectionnez
    
    RewriteEngine On

Et spécifiquement pour la mise en place des règles dans un fichier .htaccess, s'ajoutent les étapes ci-dessous :

  • Etre autorisé à suivre les liens symboliques (restriction à fin sécuritaire) : la directive Options du répertoire où il est placé doit au moins avoir la valeur FollowSymLinks (éventuellement par héritage) ou être autorisé à redéfinir cette dernière dans votre fichier htaccess.

     
    Sélectionnez
    
    Options FollowSymLinks (SymLinksIfOwnerMatch)
  • La configuration du serveur doit aussi autoriser l'usage des directives de réécriture (Rewrite*) par au moins la valeur FileInfo pour la directive AllowOverride par rapport au répertoire contenant ce fichier htaccess.

Créé le 17 décembre 2008  par julp

Vous pouvez tirer parti de l'Option MultiViews d'Apache. Vous pouvez utiliser le code suivant dans votre fichier httpd.conf ou dans un fichier .htaccess :

 
Sélectionnez

Options +MultiViews

Cette option vous permet d'ajouter du texte à la fin d'une URL.

Par exemple, si vous avez un script photos/recherche.php, c'est lui qui sera exécuté par l'URL suivante : http://www.exemple.com/photos/recherche/yogui/bovino
Vous pouvez alors récupérer /yogui depuis la variable $_SERVER['PATH_INFO']. Exemple de script recherche.php :

 
Sélectionnez

<?php
echo '<pre>';
print_r(explode('/', $_SERVER['PATH_INFO']));

Résultat de http://www.exemple.com/photos/recherche.php/yogui/bovino :

 
Sélectionnez

Array
(
    [0] => 
    [1] => yogui
    [2] => bovino
)

Si vous souhaitez avoir des URLs propres, il vous suffit de ne pas préciser l'extension du script.

Résultat de http://www.exemple.com/photos/recherche/yogui/bovino :

 
Sélectionnez

Array
(
    [0] => 
    [1] => yogui
    [2] => bovino
)

Attention toutefois car le module Apache nécessaire, mod_negociation, est connu pour provoquer des réactions parfois indésirables. La meilleure solution au manque de mod_rewrite est de changer d'hébergeur.

Créé le 17 décembre 2008  par Yogui

Lien : Documentation de la directive Options
Lien : Documentation de la négociation de contenu

Plusieurs types d'erreur liés à la réécriture peuvent se manifester :

  • L'erreur 403 Forbidden peut survenir en l'absence d'une des options permettant de suivre les liens symboliques (FollowSymLinks) qui est nécessaire au fonctionnement de la réécriture (restriction à but sécuritaire).

  • L'erreur 404 Not Found peut avoir plusieurs causes :

    • Le module de réécriture est bien chargé mais est mal activé (absence de RewriteEngine On) ;
    • Le fichier .htaccess est totalement ignoré par le serveur de par sa configuration lorsque la directive AllowOverride, pour le répertoire contenant ce fichier .htaccess (éventuellement par héritage) vaut None alors qu'au moins FileInfo est nécessaire ;
    • Les règles sont erronées dans la mesure où il n'y a pas de correspondance avec la ressource demandée ;
    • Le document vers lequel la redirection est effectuée est inexistant. Ceci pouvant notamment s'expliquer par une erreur au niveau du chemin.
  • L'erreur 500 Internal server error :

    • Le module mod_rewrite n'est pas actif. De ce fait, les directives Rewrite* ne sont pas reconnues et conduisent à ce type d'erreur ;
    • La configuration du serveur n'autorise pas l'usage des directives de réécriture (Rewrite*) par l'absence de la valeur FileInfo au niveau de la directive AllowOverride par rapport au répertoire contenant le fichier htaccess ;
    • Une règle engendre une boucle infinie. Si elle n'est pas interceptée par le navigateur avant que le serveur ne s'en rende compte de lui-même, ce dernier mettra fin au processus avec une erreur 500.

Dans tous les cas, vous trouverez sans doute une explication explicite dans les journaux du serveur si tant est que vous y avez accès.

Mis à jour le 30 mars 2010  par Julien Pauli, julp

Pour l'exemple nous supposerons que l'URL faisant l'objet d'une réécriture sera la suivante :
https://www.monsite.fr/forum/admin/index.php?page=db&start=30

Les principales variables, avec leur valeur correspondant à l'exemple, sont :

Variable Description Valeur par rapport à l'exemple
%{HTTP_HOST} Nom du serveur tel que demandé par le client par l'intermédiaire de l'entête Host www.monsite.fr
%{SERVER_NAME} Nom réel du serveur www.monsite.fr
%{REMOTE_ADDR} Adresse du client non montré
%{SERVER_ADDR} Adresse du serveur non montré
%{THE_REQUEST} La ligne complète de la requête (sans les entêtes) GET /forum/admin/index.php?page=db&start=30 HTTP/1.1
%{HTTP_COOKIE} Une chaîne regroupant l'ensemble des cookies que le client renvoie skin=blue; pref_ordre=asc
(deux cookies : skin de valeur blue et pref_ordre de valeur asc)
%{SERVER_PORT} Port d'écoute du serveur (80 : port standard du protocole HTTP et 443 pour HTTPS) 443
%{HTTP_ACCEPT} Formats acceptés par le client text/xml,application/xml,application/xhtml+xml,text/html; q=0.9,text/plain; q=0.8,image/png,*/*; q=0.5
%{REMOTE_HOST} Nom de la machine cliente ou à défaut son adresse non montré
%{REMOTE_PORT} Port utilisé par le client pour la connexion non montré
%{REQUEST_URI} La ressource telle que demandée dans la requête HTTP (voir la variable THE_REQUEST) /forum/admin/index.php
%{HTTP_REFERER} Indique la provenance de l'utilisateur (il est déconseillé de l'utiliser car celle-ci n'est pas fiable et est falsifiable) non montré
%{QUERY_STRING} Les paramètres passés dans l'URL, regroupés sous la forme d'une chaîne. Elle représente toute la partie située après le point d'interrogation (exclus), si tant est qu'elle existe. page=db&start=30
(deux paramètres : page de valeur db et start de valeur 30)
%{SERVER_ADMIN} Correspond à la valeur de la directive ServerAdmin attribué au serveur admin@monsite.fr
%{DOCUMENT_ROOT} La racine du serveur telle que définie par la directive DocumentRoot /usr/local/www/apache22/data/
%{REQUEST_METHOD} Méthode HTTP employée par la requête (généralement GET ou POST) GET
%{HTTP_USER_AGENT} Identifiant du client Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11
%{SCRIPT_FILENAME} et %{REQUEST_FILENAME} Chemin complet (absolu) du document appelé /usr/local/www/apache22/data/forum/admin/index.php
%{SERVER_PROTOCOL} Description du protocole employé HTTP/1.1
%{HTTPS} Booléen (valeur on ou off) indiquant l'usage ou non du protocole sécurisé (peut être utilisée indépendamment de la présence ou non du module ssl) on

A travers cet exemple il n'est possible de présenter que les variables liées à l'adresse demandée (le principal) car elles se font en réalité bien plus nombreuses :

  • %{HTTP:X} : en référence à l'entête HTTP X
  • %{ENV:X} : désigne la variable d'environnement X
  • %{SSL:X} : la variable d'environnement SSL X (en l'absence du module ssl, leur valeur sera une chaîne vide)
  • Toutes les variables relatives à la date et/ou l'heure : %{TIME_YEAR}, %{TIME_MON}, %{TIME_DAY}, %{TIME_HOUR}, %{TIME_MIN}, %{TIME_SEC}, %{TIME_WDAY}, %{TIME}
Créé le 17 décembre 2008  par julp

La réécriture en boucle infinie se présente d'elle-même dans le cas notamment où l'expression rationnelle utilisée au niveau d'une règle de réécriture (son premier paramètre) est telle qu'il y a correspondance sur le document vers lequel on redirige (le deuxième paramètre de RewriteRule).

Un exemple simple et fréquent de règle mal conçue pourrait être le suivant :

 
Sélectionnez

RewriteRule (.*) /index.php?page=$1

Ainsi, lorsque le document index.php sera demandé, après une première redirection interne, se verra par la suite indéfiniment réécrit en index.php?page=index.php.

Pour l'éviter, par rapport à l'exemple précédent, il convient d'ajouter une condition (directive RewriteCond) pour écarter l'index lui-même.

 
Sélectionnez

RewriteCond %{REQUEST_URI} !=/index.php # Le chemin complet du script tel qu'apparaissant dans l'URL
RewriteRule (.*) /index.php?page=$1

Ce perpétuellement recommencement pourra être détecté par le client sinon par le serveur (génération d'une erreur 500 avec consignation de l'incident dans le journal d'erreur).

Ce phénomène peut aussi apparaître sur d'autres parties de l'URL : la partie query string en est un autre exemple avec la retransmission d'un paramètre qui est mal géré.

Créé le 17 décembre 2008  par julp

La directive RewriteLog indique le chemin vers le fichier dans lequel sera détaillé le processus de réécriture et son associée, RewriteLogLevel, précise le degré de verbosité des différentes opérations effectuées en interne. Sa valeur s'échelonne de 0, pour ne générer aucune entrée dans le journal, à 9 pour obtenir un maximum d'informations.

Plus la valeur de la directive RewriteLogLevel sera important plus sa verbosité sera élevée. Elle pourra avoir pour conséquence d'écrire quantité d'informations dans son journal et avoir un impact néfaste sur les performances du serveur.

Créé le 17 décembre 2008  par julp

Par défaut toute cette partie de la requête est transmise (copiée) lors de la redirection. Mais dès lors que vous les manipulez par une règle, même pour ajouter simplement une telle variable, vous devez mentionner l'option QSA pour la redirection concernée pour ne pas les perdre et retrouver ce comportement par défaut.

La directive RewriteRule ne teste la correspondance que sur la partie chemin de l'URL. Pour tester les variables qui composent la partie query string vous devrez faire appel à la directive RewriteCond dont son premier paramètre aura pour valeur %{QUERY_STRING}, variable désignant ce morceau de l'URL (voir exemple ci-bas).

Voici quelques opérations qu'il est possible de réaliser :

  • Pour supprimer entièrement la partie query string lors d'une redirection, et en tenant compte des spécificités évoquées plus haut, faites apparaître le point d'interrogation à la fin de la requête de redirection de votre directive RewriteRule :

     
    Sélectionnez
    
    RewriteRule ^page_avec_parametres\.php$ page_sans_parametre.php?

    Lorsque vous ferez appel à la page page_avec_parametres.php vous serez redirigés sur page_sans_parametres.php. Tous les paramètres passés par URL seront supprimés lors de l'appel à ce second script.

  • Sans l'option QSA les anciennes variables ne seraient pas transmises et nous n'obtiendrions que le paramètre nouvelle_variable par rapport à l'exemple ci-dessous. Il est donc nécessaire de mentionner l'option QSA afin de conserver ces paramètres lors de l'opération de réécriture :

     
    Sélectionnez
    
    RewriteRule ^page_d_origine\.php$ page_de_destination.php?nouvelle_variable=nouvelle_valeur [QSA]

    Ici quels que soient les paramètres fournis lors de l'appel au script page_d_origine.php ils seront recopiés mais une nouvelle variable, nommée nouvelle_variable ayant pour valeur nouvelle_valeur, sera ajoutée à celles d'origine.

  • Il est possible de n'effectuer qu'un test de présence d'une telle variable. Dans l'exemple ci-dessous, est interdit (le serveur renverra une erreur 403) tout accès à l'index si le paramètre secret magique n'est pas stipulé.

     
    Sélectionnez
    
    RewriteCond %{QUERY_STRING} !(?:^|&)magique(?:=|&|$)
    RewriteRule ^index\.php$ - [F]

    Note : le contrôle peut également et parfaitement porter sur plusieurs paramètres et sur leur valeur respective.

  • Réécrire un chemin purement virtuel dont chaque partie deviendrait des paramètres. Par exemple, une URL telle que http://www.monsite.fr/livredor/ serait en réalité http://www.monsite.fr/index.php?page=livredor :

     
    Sélectionnez
    
    # Exemple 1 (chemin simple)
    RewriteRule ^([^/.]+)/?$ index.php?page=$1 [QSA]
     
    # Exemple 2 (double chemin)
    RewriteRule ^([^/]+)/([^/]+)/?$ index.php?module=$1&action=$2
  • Et enfin, l'opération inverse du cas précédent, à savoir faire de paramètres le chemin vers le document réel à appeler, en somme utiliser une URL http://monsite.fr/?module=a&action=b pour servir http://monsite.fr/a/b/ :

     
    Sélectionnez
    
    RewriteCond %{QUERY_STRING} (?:^|&)module=([^&]+)&action=([^&]+)
    RewriteRule ^(?:index\.php)?$ /%1/%2/
Créé le 17 décembre 2008  par julp
  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2010 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.