Réécriture d’URLs NGinx

NGinx, après Apache, fait partie des serveurs web les plus populaires. Une URL Uniform Resource Locator est une adresse qui permet d’identifier une ressource telle qu’une page web. Une URL propre ou préparée pour le référencement SEO Search Engine Optimization est une adresse facile à lire, à retenir, qui indique à l’utilisateur le contenu qu’il peut trouver.

Le logo NGINX et le texte Rewrite URL, en fond la Playa de Las Teresitas à Tenerife

Le module ngx_http_rewrite_module est utilisé pour modifier l’URI de demande à l’aide d’expressions régulières PCRE Perl Compatible Regular Expressions, et permet de renvoyer des redirections et de sélectionner conditionnellement des configurations.

URI, URL ?

  • Une URI Uniform Resource Identifier est un identifiant d’une ressource sur le réseau, telle qu’une page web, un livre, un document …
  • Une URL est un identifiant spécial qui indique le protocole pour accéder à une ressource telle que http, httpsftp, sftp. Ce sont les plus fréquents, mais il y en a d’autres.

Si le protocole (httpsftp, …) est présent devant le domaine, cela s’appelle une URL—sinon c’est une URI.

Objectif

Lorsque l’on accède à une ressource en base de données, on fait fréquemment appelle à son identifiant id dans une table. Le paramètre est défini après le nom de la page suivi d’un point d’interrogation, par un nombre entier :

Ce n’est pas très parlant, l’id correspond à une page qui présente le numéro 67 d’une revue de Science-Fiction Galaxies SF. Il serait donc bien plus intérressant de pouvoir écrire :

De même, pour lire le sommaire de ce numéro, on accède à la page :

qu’il serait beaucoup mieux de référencer à l’adresse :

URL Rewriting

L’URL rewriting est une technique qui utilise un moteur de réécriture pour modifier l’apparence de l’URL. L’URL Rewriting est rapide et flexible et il n’est pas obligatoire de renommer les dossiers de l’application. Cela permet de donner au serveur web (NGinx) l’information nécessaire afin d’interpréter l’adresse requise.

NGinx et l’URL Rewriting

NGinx (prononcez engine X) est un serveur http Hypertext Transfer Protocol. Il dispose de fichiers de configuration par défaut qui réside habituellement dans le dossier /usr/local/nginx/conf ou /opt/nginx/conf ou /usr/local/etc/nginx, mais plus fréquemment dans /etc/nginx. Le fichier contient :

Le symbole # indique un commentaire.

Le fichier de configuration d’un site, contient une directive server, dans laquelle on trouve des directives location en fonction du type de fichiers demandés. Par exemple pour un site en php, on trouve dans /etc/nginx/sites-available des fichiers de configuration qui sont liés symboliquement dans /etc/nginx/sites-enabled. Les sites actifs d’un serveur se trouvent dans sites-enabled référencés, à la ligne 55 du fichier précédent, par une wildcard * : /etc/nginx/sites-enabled/*

Un exemple simple

Supposons que l’on a l’URL suivante :

Et l’on désire que les utilisateurs accède à cette page avec l’URL :

On peut alors créer un bloc location simple :

Fonctionnement

location = /generateurs-bases64 : Comme le signe = est utilisé, le bloc location capture l’URL :

Mais pas :

ni

Si l’on enlève le signe =, le bloc location capturera les URLs ci-dessus, c’est-à-dire n’importe quelle URL contenant /generateurs-base64. On peut utiliser location ~ pour capturer des blocs avec des expressions régulières, ou location ~* pour que l’expression régulière soit insensible à la casse. Si l’on ne met pas le tilde ~, NGinx attend une expression régulière.

L’instruction rewrite indique une règle de réécriture, ^/generateurs-base64$ est une expression régulière, ^ repésente le début de la chaîne, $ la fin. On recherche la chaîne qui se trouve après le protocole http ou https et le nom de domaine domain.tld (URI), soit https?://domain.tld/mon-adresse.

Une directive rewrite redirige vers une URI avec le code 301 ou 302, c’est-à-dire une redirection permanente ou temporaire, et est de la forme :

Dans notre exemple, break est un flag drapeau. Les flags disponibles sont :

  • last : arrête le traitement de directives rewrite et lance la recherche d’un nouvel emplacement correspondant à l’URL,
  • break : n’effectue pas le traitement de directives rewrite avec le même motif si d’autres suivent,
  • redirect retourne une redirection temporaire avec le code 302, utilisé seulement si la chaîne ne commence pas par http://, https://, or $scheme,
  • permanent retourne une redirection permanente avec le code 301.

Parenthèses capturantes

Expression régulière

Dans une expression régulière, un motif est capturé lorsqu’il est entre parenthèse. Par exemple, le motif galaxies-([a-z]) capture ce qui suit galaxies- et le place dans la variable $1. S’il y a deux parenthèses, les variables capturées seront $1, $2 et ainsi de suite. Donc, pour notre exemple https://galaxies-sf.com/sommaire-revue-67.html, on va capturer sommaire (puisque j’aurai la même chose avec editorial, …), revue et 67 (sachant que l’on peut avoir aussi 67bis). Le motif de l’expression régulière est alors /([a-z])-([a-z])-([a-z0-9])\.html. [a-z] représente les lettres minuscules, 0-9 sont les chiffres, un point représente n’importe quel caractère, en l’echappant avec un backslash \, il capture un simple point .. On cherche alors à mettre en paramètre $_GET[] de l’URL, le type de revue et le numéro de la revue. On sera obligé de modifier le fichier sommaire.php pour aller récupérer l’id en base de données connaissant le type et le numéro de la revue.

Règle de réécriture

Si l’on indique l’expression régulière avec un tilde ~, il ne doit pas y avoir d’espace entre le ~ et la regex à savoir le caractère caret ^ de début de chaîne.

Mais, je veux également rediriger l’URL galaxies-revue-57.html vers la page d’accueil index.php. On écrit donc une deuxième règle rewrite avant celle que l’on vient d’écrire. En principe, la première règle qui capture une URL l’emporte, mais on peut faire suivre la directive avec le flag last ou break, pour indiquer que la recherche est terminée.

On écrit les lignes de réécriture dans le bloc server. Ainsi pour les fichiers index.php, sommaire.php et editorial.php qui fonctionnent en utilisant la variable $_GET['id'], on change le début du traitement en retrouvant cet identifiant en base de données avec les variables $_GET['type'] et $_GET['revue']. WordPress fait la même chose avec le slug ou postname unique d’un article.

Il semble que NGinx n’apprécie pas l’espace entre le tilde ~ indiquant la ReGex et le caret ^ indiquant le début de la chaîne :

Cette directive renvoie l’ erreur NGinx: [emerg] invalid number of arguments in "rewrite" directive in /etc/nginx/sites-enabled/galaxies-sf.murvielinfo.com:30. Si l’on omet le tilde ~, ou si l’on ne met pas d’espace entre le tilde ~ et le caret ^, il n’y a pas d’erreur.

En fait je pense que si l’on met cet espace, NGinx attend l’expression de remplacement, le motif étant indiqué après la directive location, comme dans l’exemple ci-après.

L’adresse URL sera par exemple de la forme https://galaxies-sf.com/galaxies-revue-67.html. Ce qui nous intéresse est la chaîne après le nom de domaine. Le suffixe est .html, on va donc cibler dans un bloc location les chaînes se terminant par .html. Si le motif est reconnu, on renvoie vers un fichier php, par exemple index.php, avec des arguments $_GET[].

Dans ce cas, on met plusieurs blocs locations pour chaque rewrite. Dans notre cas, on teste la fin de la chaîne .html, et l’on rédéfinit le motif, en fonction de ce que l’on trouve dans l’URL. Il y a plusieurs façons de faire.

Bloc location

Ainsi l’URL : https://galaxies-sf.com/galaxies-revue-67.html sera réécrite en https://galaxies-sf.com/index.php?type=revue&revue=67. Il n’y a plus qu’à gérer les variables $_GET['type'] et $_GET['revue'] dans le fichier index.php, c’est-à-dire aller chercher l’id en base de données avec ces deux données, pour laisser le traitement qui suit inchangé.

Le flag permanent indique une redirection 301 permanente. Si on l’ajoute à nos directives rewrite, l’URL indiquée dans la barre d’adresse changera également, par exemple https://galaxies-sf.com/galaxies-revue-67.html changera en https://galaxies-sf.com/index.php?type=revue&revue=67. Ce n’est pas vraiment ce que l’on recherche.

L’URL https://galaxies-sf.com/galaxies-revue-67.html est beaucoup plus jolie, on peut bien mieux s’en rappeler, elle indique ce que l’on va trouver et sera bien mieux référencée que l’URL https://galaxies-sf.com/index.php?id=74. On veut néanmoins que l’URL avec le paramètre id continue de fonctionner. Certains sites ont peut être déjà inscrit en lien cette URL.

Test des règles de réécriture NGinx

On teste la configuration. Si cela ne produit aucune erreur, on redémarre le serveur http :

Erreur 404, page non trouvée :

On peut indiquer au serveur http NGinx ce qu’il faut faire si la page n’est pas trouvée. C’est ce que l’on appelle une erreur 404. Les moteurs de recherche n’aiment pas cela. Pour optimiser un site en terme de SEO, il faut que les liens internes (dans le site vers le site) ne renvoient aucune erreur 404. Malheureusement, cela peut arriver. Mais, on peut rediriger la page 404 par defaut vers une page plus personnalisée dans la configuration NGinx.

Pour un site de taille conséquente, ceci peut être très long à faire, et il n’est pas sûr qu’il ne reste pas quelque chose. La page 404 montrée par défaut est une page blanche avec 404 Not Found indiquée :

Page d'erreur 404 pour une URL erronée

Directive NGinx

Pour rediriger l’erreur 404 vers une page personnalisée, on écrit dans le fichier de configuration, dans le bloc server :

On crée une nouvelle page page-inconnue.php, et l’on indique que la page n’a pas été trouvée. Ainsi, les pages non trouvées sont redirigées vers cette page que l’on peut ainsi personaliser :

Page inconnue personnalisé avec le menu, le fond de la page, et la mention Page Inconnue indiquée

Test de la configuration

On écrit dans le fichier index.php, au tout début :

Ainsi, on affiche les variables $_GET. On entre l’adresse : https://domain.tld/galaxies-revue-67.html. Le retour est :

Cela fonctionne bien.

Écriture du code PHP

On recherche alors l’id dans la base de données. On écrit donc dans index.php :

Ainsi, les anciennes URLs fonctionnent et les nouvelles aussi.

Mais ce qui serait encore mieux, c’est lorsque l’on tape l’adresse https://galaxies-sf.com/sommaire.php?id=74 ou l’on clique sur un lien de cette adresse, on soit redirigé vers https://galaxies-sf.com/sommaire-revue-67.html, et que cette nouvelle adresse remplace l’ancienne dans la barre d’adresse. Cela évitera la duplication de contenus, c’est-à-dire un même contenu à des adresses différentes. Cela permettra que d’anciens liens, référencés sur des sites externes fonctionnent toujours et renvoient sur la bonne page, avec la nouvelle adresse URL inscrite dans la barre d’adresse. C’est réellement très important en terme de SEO.

La redirection doit être du type permanent 301. La redirection 301 permanente indique au navigateur web et aux robots des moteurs de recherche que la page visitée a définitivement changé d’adresse. Le caractère définitif de cette redirection indique aux moteurs de recherche qu’ils doivent mettre à jour leur index. Ceci se fait en PHP à l’aide de l’instruction header() qui permet de spécifier l’en-tête http. On indique le type de redirection, et l’emplacement de celle-ci.

Et hop, on a nos redirections, nos jolies URLs, on est prêt pour le SEO. Il ne reste plus qu’à faire une jolie page 404, où l’on peut proposer au visiteur de visiter d’autres pages.

Soumettre un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables.