FAQ du serveur HTTP Apache
FAQ du serveur HTTP ApacheConsultez toutes les FAQ
Nombre d'auteurs : 9, nombre de questions : 47, dernière mise à jour : 14 juin 2021
- Comment créer une arborescence virtuelle ?
- Quelles conditions doit-on réunir pour pouvoir utiliser la réécriture ?
- Comment utiliser la réécriture d'URL avec un hébergeur qui n'a pas mod_rewrite ?
- Comment déchiffrer les erreurs serveur renvoyées dans le cadre de la réécriture ?
- Quelles sont les différentes "variables" et à quoi correspondent-elles ?
- Comment éviter de réécrire une URL en boucle ?
- Comment déboguer la réécriture d'URL ?
- Comment faire de la réécriture sur la partie dite "Query String" ?
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 :
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 :
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)
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 :
-
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é.
-
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électionnezRewriteEngine
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électionnezOptions
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.
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 :
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 :
Résultat de http://www.exemple.com/photos/recherche.php/yogui/bovino :
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 :
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.
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.
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}
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 :
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.
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é.
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.
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électionnezRewriteRule
^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électionnezRewriteRule
^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électionnezRewriteCond
%{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électionnezRewriteCond
%{QUERY_STRING} (?:^|&)module=([^&]+)&action
=([^&]+)RewriteRule
^(?:index\.php)?$ /%1/%2/