Traitement d’une url par apache
Niveau :
Résumé : apache, virtualhost, configuration
Que se passe-t-il lorsqu'apache reçoit une requête ?
La question peut paraître anodine jusqu'à ce qu'on ait à écrire un fichier de configuration un peu complexe. Il faut alors avoir une idée de l'ordre dans lequel les opérations sont effectuées.
Commençons par un aperçu rapide :
-> récupération du virtualhost concerné
-> récupération de la partie requête
-> rewrite rules et redirect
-> alias et réécriture de la requête nom de fichier
-> traitement par <Directory>, <DirectoryMatch>, .htaccess, <Files>, <FilesMatch>, <Location> et <LocationMatch>
-> droits d'accès
-> traitement du fichier en fonction de son type.
Ouf c'est long ! Comme cet article, alors prenez votre temps ...
Traitement de l'URL
Pour chaque requête, apache relit sa configuration (en fait il récupère la version parsée en mémoire). Ensuite il parcourt les éléments dans l'ordre, les compile en une seule conf puis la utilise cette conf spécifiquement pour cette requête.
Virtualhost
Bon ca c'est facile, on se base sur les ServerName définis dans les <Virtualhost>. Si on n'en trouve pas, on cherche dans les ServerAlias, si on n'en trouve pas on cherche encore, mais cette fois avec les wildcard (*.mondomaine.com), si on ne trouve toujours pas, on prend le premier <Virtualhost> qui a été dacléré. Et enfin s'il n'y a pas de virtualhost, on prend le DocumentRoot défini à la racine du serveur apache lui-même.
Voilà on a trouvé le virtualhost, maintenant on prend la requête, qui est la partie située à droite de l'URL après l'hôte et le port.
Transformation de l'URL
Contrairement à ce qu'on pourrait penser, lorsqu'il y a modification de l'url, il n'y a pas de gestion de droits d'accès sur la requête originale, seulement sur l'url modifiée (par rewriterule en général).
On traite d'abord les RewriteRule, dans l'ordre de leur priorités.
Si aucune ne correspond, on traite ensuite les Redirect et les RedirectMatch dans l'ordre de leur écriture. Attention on prend aussi en compte ceux qui sont dans les <Location> qui correspondent, mais on fait comme s'ils avaient été écrits à la racine. C'est-à-dire qu'on n'enlève pas le préfixe du location pour les traiter.
On traite ensuite les Alias, AliasMatch, ScriptAlias et ScriptAliasMatch dans l'ordre de leur apparition. Ce traitement fournit le nom de fichier réel à utiliser pour une URL donnée.
Si on ne trouve pas d'alias on ajoute le DocumentRoot à la requête pour obtenir le chemin complet du fichier.
Configuration et droits d'accès
A partir de maintenant on repart de la configuration du virtualhost et pour chaque section on prend la configuration qui correspond à la requête en cours. Et à la fin on fusionne les configurations récupérées selon une règle de fusion dépendant de chaque module.
C'est complexe et chiant à retenir, donc pour simplifier retenez que les configurations spécifiques aux droits d'accès sont en mode remplacement, c'est-à-dire que la dernière configuration remplace toutes les autres.
Directory et DirectoryMatch
On sait maintenant quel chemin doit être lu, on parcourt l'arborescence pour savoir si c'est un fichier et si on peu le lire s'il a un vrai chemin sur le système ...
On part de / et au fur et a mesure qu'on descend dans le système de fichier on vérifie les <Directory>, puis les .htaccess, puis les <DirectoryMatch> dans l'ordre pour chacun des répertoires. On a donc séquentiellement pour par exemple /var/www :
- <Directory />
- /.htaccess
- <DirectoryMatch />
- <Directory /var>
- /var/.htaccess
- <DirectoryMatch /var>
- <Directory /var/www>
- /var/www/.htaccess
- <DirectoryMatch /var/www>
Toutes les sections qui correspondent sont accumulées dans la configuration en cours.
Attention ! Si l'option FollowSymLinks est activée, on fait la correspondance sur les liens symboliques avant de les déréférencer. Si l'option est désactivée, on la fait sur les liens après les avoir déréférencés. C'est assez contre intuitif !
Files et FilesMatch
Une fois arrivé au bout, on a un fichier, on lit alors les sections <Files> et <FilesMatch> dans l'ordre de leur apparition, y compris celles qu'on a trouvé dans les .htaccess ou les <Directory>.
Notez que ces sections ne prennent en compte que le nom de fichier, sans chemin.
Attention, même remarque que précédemment sur les liens symboliques : "Si l'option FollowSymLinks est activée, on matche sur les liens symboliques avant de les déréférencer. Si l'option est désactivée, on matche sur les liens après les avoir déréférencés."
Location et LocationMatch
Maintenant il nous reste à prendre en compte tous les <Location> et <LocationMatch> de la configuration qui correspondent à notre URL. Cette fois on les prend séquentiellement et uniquement en fonction de l'url.
Attention les étapes de réécriture de règle sont passées, on matche donc sur l'url réécrite.
Configuration des droits
Dans le cas des droits d'accès, les blocs de directives se remplacent. C'est-à-dire que si vous avez une série de "order / allow / deny" dans une section, elle remplace intégralement toute autre série de "order / allow / deny" que vous pourriez trouver dans une section précédente.
Attention ceci est valable pour chacun des modules séparément.
Un exemple pour être plus clair :
<Location /> order allow,deny </Location> <Directory /html> deny from all AuthUserFile users.txt </Directory> <DirectoryMatch /> AuthUserFile web.txt </DirectoryMatch> <Directory /> order deny,allow allow from all AuthUserFile admins.txt </Directory>
Le premier <Directory> est lu, puis il est remplacé par le 2e <Directory>, puis il est remplacé par le <DirectoryMatch> puis par le <Location> intégralement, mais séparément pour le module authz_host (order, allow, deny) et le module authnz_user (AuthUserFile). On a donc pour une requête qui matcherait les 3 sections la configuration suivante :
order allow,deny AuthUserFile web.txt
Pas évident hein :-) Surtout que cette règle n'est pas la même pour d'autres modules comme mod_rewrite.
Traitement des droits
Le traitement des droits lui-même est particulier.
Si on est en satisfy all (par défaut) :
- On prend tous les modules de traitement des droits d'accès et si l'un d'entre eux interdit l'accès, on interdit l'accès.
- Puis on prend tous les modules d'authentification utilisateur et si l'un d'entre eux autorise l'accès ou s'il n'y en a pas, on autorise l'accès.
Si on est en satisfy any :
- On prend tous les modules de traitement des droits d'accès et si l'un d'entre eux interdit l'accès :
- On demande son avis aux modules d'authentification, si l'un d'entre eux autorise l'accès ou s'il n'y en a pas, on autorise.
Rewrite (again)
Arrivé ici, on repasse dans les RewriteRules Mais cette fois on ne traite que le cas particulier des rewrite dans les sections <Location>, <Directory>, <Files> et .htaccess
Ces rewrite se cumulent cette fois (contrairement aux module d'accès, mais toujours selon le même parsing vu précédemment).
Ces rewrites sont cette fois relatifs, contrairement aux rewrite globaux. Ce qui veut dire qu'on les écrit par rapport à une racine qui est l'endroit où la règle est écrite.
Réponse
Cool maintenant on a notre requête nettoyée et on sait vers quelle fichier elle pointe.
Reste à la traiter.
Filter
On cherche tous les filtres (input et output) associés à cette url. Par exemple il y a mod_include, vous savez, pour les fichier .shtml qui contiennent des truc genre :
<!--#echo var="DATE_LOCAL" -->
Il y a aussi les filtres pour compresser (oui pas besoin de zipper en php, apache peut le faire tout seul).
Tout ceci avec SetInputFilter et SetOutputFilter.
Handler
Ensuite on cherche le handler associé à ce type de fichier. Il y a bien sur le handler fichier (incroyable), mais aussi le handler php, le handler perl (sisi), le handler cgi, mais aussi le handler proxy, et tous ceux que vous pourriez définir avec SetHandler .
On et hop lance le tout : inputfilter -> handler -> outputfilter.
Conclusion
En résumé c'est le bordel ! Celui qui a écrit ça devait en avoir pris une sacrée dose et pas que de la farine. Probablement un pote de celui qui a fait X11 ...
Ne supposez jamais que ça marche comme vous le pensez, testez à chaque modification de votre conf.
Espérons que le prochain apache en développement tiendra ses promesses et nettoiera un peu la gestion de la configuration et surtout des droits d'accès. Sinon je prédis un avenir merveilleux pour toutes les alternatives soit disant "légères" comme lighthttpd ou nginx.
Tags:planet-libre, Serveur