Alias, redirections & réécritures d’URL

Luc Didry, à partir des cours de Sébastien Jean. Licence CC-BY-SA
Your wish is my command. But be careful what you wish for.
Le neuvième docteur

Télécharger le PDF

Alors que la majeure partie des URL1 reçues par un serveur Web désignent un chemin relatif par rapport à la racine du serveur (directive DocumentRoot pour Apache, root pour Nginx), il est également possible d’associer certaines URL à des emplacements qui ne suivent pas cette règle. Dans ce contexte :

  • Un alias permet d’associer un emplacement non standard à une URL. Tout est alors réalisé directement sur le serveur, l’opération étant invisible2 pour le client.
  • Une redirection consiste à associer une nouvelle URL à une URL reçue en requête. C’est alors au client de suivre la nouvelle URL… ou pas : une redirection peut être interne. C’est alors au serveur de se débrouiller.

Ces fonctionnalités sont disponibles via deux modules Apache différents, idem pour Nginx, à ceci près que l’un des deux est ngx_http_core_module3, c’est à dire celui qui fournit la possibilité d’utiliser Nginx comme serveur web.

NB : dès que vous avez besoin d’un module, prenez soin d’aller lire la documentation du module au moins une fois. Ça ne fait pas de mal et vous aurez des réponses avant de vous poser les questions (du genre, « Dans quelle contexte puis-je utiliser cette directive ? »)4.

1 Alias

1.1 Apache

Le module mod_alias5 est a priori le plus utilisé pour gérer les alias et les redirections. Il est généralement assez flexible pour répondre à la majorité des besoins et doit être utilisé en priorité lorsque son usage permet de résoudre un problème donné.

La gestion des alias s’appuie sur les directives suivantes :

  • Alias, permettant d’associer un nom de dossier à une URL, sachant que ce dossier n’est pas obligatoirement sous la racine du serveur (le DocumentRoot). Son emplacement est désigné par un chemin absolu. Attention : si l’URL déclarée par Alias se termine par un /, les requêtes devront également en comporter un.

     Alias /images /usr/local/share/images
     Alias /errors/include/ /usr/local/share/apache2/errors/
  • AliasMatch, qui fonctionne de la même manière que la directive Alias, mais qui permet d’identifier les URL concernées à l’aide d’expressions régulières.
  • ScriptAlias, fonctionnant également de la même manière de Alias, mais désignant un répertoire dans lequel des scripts CGI pourront être exécutés6.
  • ScriptAliasMatch, qui fonctionne selon le même principe que ScriptAlias en utilisant des expressions régulières.

1.2 Nginx

Deux directives peuvent être utilisées pour créer des alias dans Nginx : alias et root.

On les utilisera à l’intérieur d’un contexte location :

location /images {
    alias /usr/local/share/img/;
}
location /errors/include/ {
    root /usr/local/share/apache2/errors/;
}

La documentation d’alias indique qu’il est préférable d’utiliser root quand la location correspond à la dernière partie de l’alias (/images/ et /usr/local/share/images/ par exemple).

Si la location est utilisée avec une regex, celle-ci pourra comporter des captures qui seront utilisées dans l’alias :

location ~ ^/users/(.+\.(?:gif|jpe?g|png))$ {
    alias /data/w3/images/$1;
}

Il y a une différence de comportement entre root et alias :

location /foo {
    root /var/www;
    # alias /var/www;
}

Si l’on demande /foo/bar/index.html, avec root, on aura le contenu de /var/www/foo/bar/index.html et avec alias, on aura /var/www/bar/index.html.

2 Redirections

2.1 Apache

La gestion des redirections s’appuie quant à elle sur les directives suivantes :

  • Redirect (qui est aussi fourni par mod_alias), qui permet d’effectuer des redirections « simples », avec une syntaxe basée sur les préfixes : Redirect [code d’état] ancien_chemin nouveau_préfixe.
    Ainsi, si l’URL d’une requête commence par ancien_chemin, toute l’URL correspondant à la requête est transformée en substituant dans la requête d’origine la base de l’URL et ancien_chemin par nouveau_préfixe. Le nouveau_préfixe peut être une URL absolue, avec protocole et nom d’hôte ou être un chemin URL commençant par un /, auquel cas ce seront le protocole et nom d’hôte du serveur qui seront utilisés.
    Les codes d’état utilisables sont de la forme 3xx ou correspondent à une des valeurs suivantes : permanent (301), temp (302), seeother (303), gone (410, pas de nouveau préfixe d’URL fourni dans ce cas).

     # redirection de http://localhost/support/find.php
     # en http://support.example.org/find.php
     Redirect 301 /support http://support.example.org/
     Redirect permanent /support http://support.example.org/
  • RedirectMatch, qui fonctionne comme la directive Redirect, mais en considérant des expressions régulières. On rappelle que les expressions capturées (entre parenthèses) peuvent être utilisées dans la dernière partie de la directive grâce à $1, $2, $3, etc.

     RedirectMatch permanent (.\*)\.gif$ http://example.org/icons/$1.png
  • RedirectTemp : permet de faire une redirection temporaire, renvoyant donc un code 302, et est strictement équivalente à Redirect temp …
  • RedirectPermanent : idem que pour la directive précédente, avec permanent à la place de temp.

Pourquoi utiliser les deux dernières directives si elles sont équivalentes à Redirect xxx ? Sans doute pour la lisibilité (un terme comme temp étant plus parlant qu’un code de retour, même si on finit par les connaître par cœur) et sans doute pour l’économie d’un caractère à taper :-).

Blague à part, Les redirections permanentes et temporaires sont suffisamment souvent utilisées pour avoir leur propre directive, qui indique d’un coup d’œil de quelle redirection il s’agit.

2.2 Nginx

On utilisera la directive return du module ngx_http_rewrite_module7, avec généralement en argument un code de retour (en chiffres) et une URL (absolue ou relative).

return 301 https://support.example.org/;
return 301 /foo/bar;

Il est possible de retourner uniquement un code (return 404;), un code accompagné d’un texte (return 401 "foo";) ou juste une URL (return /foo/bar;).

Pour spécifier dans quel cas on redirige, on placera return dans un contexte location ou if :

location /support {
    return 301 http://support.example.org/;
}

3 La réécriture d’URL

3.1 Apache

Tout comme mod_alias, le module mod_rewrite8 permet de gérer les alias et les redirections, mais de façon beaucoup plus fine. Il est ainsi beaucoup plus puissant et beaucoup plus complexe. À titre d’exemples, il est ainsi possible avec ce module de :

  • Faire tout ce que mod_alias permettait déjà de faire en étendant ses possibilités.
  • Définir des conditionnel permettant d’activer ou non certaines règles en fonction de la condition testée. Les conditions peuvent porter sur des variables internes du serveur, comme sur des valeurs systèmes ou des valeurs liées aux requêtes reçues.
  • Faire des comparaisons entre chaînes de caractères.
  • Tester l’existence de pages et, dans la négative, d’en créer une de toute pièce.
  • De faire appel à des programmes extérieurs pour assister la réécriture.
  • Enfin, ses fonctionnalités peuvent être configurées au niveau du serveur, d’un répertoire ou d’un hôte virtuel.

C’est un module très complet et très complexe, à utiliser lorsque la situation le nécessite.

Plutôt que de réécrire la documentation, je vous encourage à aller la lire directement sur http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html.

NB : Pour activer le moteur de réécriture dans les contextes <Directory> et .htaccess, vous devez définir "RewriteEngine On" et "Options FollowSymLinks".

3.2 Nginx

Ici, nous utiliserons la directive rewrite. Elle utilise en argument une regex qui sera comparée à l’URL demandée, l’URL de redirection (qui pourra réutiliser des termes capturés dans la regex) et éventuellement un flag.

server {
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  last;
    return  403;
}

Les réécritures sont traitées séquentiellement et peuvent donc s’exécuter l’une après l’autre. Lorsque l’URL de redirection commence par http:// ou https://, le traitement s’arrète et la redirection est retournée au client.

Pour stopper le traitement, on utilisera les flags suivants :

  • last : les autres rewrite ne sont pas regardés et Nginx regarde comment traiter la requète avec la nouvelle URL ;
  • break : les autres rewrite ne sont pas regardés mais Nginx cherche à traiter la requète sans repartir de zéro (contrairement à last) ;
  • redirect : redirection temporaire (avec le code 302) ;
  • permanent : redirection permanente (code 301).

4 Exercices

Les exercices sont à rendre sur https://lstu.fr/asrall-web-tp4. Envoyez vos réponses dans un fichier appelé tp4_votre_nom.txt.

Vous pouvez envoyer un seul fichier pour un binôme, mais pensez bien à mettre vos deux noms dans le nom du fichier.

  1. Apache : Quelles sont les fonctionnalités offertes par le module mod_dir9 ? Quelle manipulation simple permet de mettre en évidence son rôle dans les URL qui ne se terminent pas par des / ?
  2. Apache et Nginx : Testez les alias et les réécritures sur quelques exemples.
  3. Mettez en place des réécritures de votre choix. Cependant :
    • Apache : pour vos tests mettez en place des logs spécifiques pour les réécritures,
    • essayez vos règles dans des .htaccess (Apache) et dans des vhosts spécifiques (Apache et Nginx),
    • Apache et Nginx : mettez en place des réécritures conditionnelles. Par exemple en réécrivant l’URL si la requête provient d’une certaine IP.
  4. À l’aide de l’outil ab, essayez de mettre en avant l’incidence que peut avoir une règle de réécriture sur les performances d’Apache et Nginx.

https://asrall.fr