Pour diverses raisons (Duplicate Content, modification de structure d’URL, nettoyage d’anciennes URL), vous pouvez être amenés à remplacer l’ensemble de certains caractères dans vos URL (ex: _, +, |, etc.) par d’autres caractères (ex: tiret « -« ). Vous avez alors la possibilité de créer une règle de redirection pour remplacer toutes les occurences via une seule RewriteRule. Mais si vous avez plusieurs occurences, cela risque de générer des redirections en chaîne ce que Google risque de peu apprécier…
Voici des exemples de ce qu’il ne vaut mieux pas faire, et une solution qui me semble adapté à ce genre de remplacement en chaîne dans les URL.
Ce que l’on veut faire
Nous avons plusieurs occurrences d’une chaîne à remplacer.
En gros on veut passser de
à ça
C’est clair? Dans l’exemple que j’ai choisi, nous voulons rediriger toutes les URL http://www.yapasdequoi.com/blog/search/suite_de_mots_cles –> http://www.yapasdequoi.com/blog/search/suite–de–mots–cles (remplacer underscore par tiret)
La fausse bonne idée n°1
On pourrait dans un premier temps effectuer une redirection de ce type:
RewriteRule ^/search/([^_]*)_([^_]*)$ /search/$1-$2 [L,R=301]
Décodage: Redirige /search/(nimporte quels caracteres sauf un underscore)_(nimporte quels caracteres sauf un underscore) vers /search/(ensemble de caractères définit par les 1ères paranthèses)–(ensemble de caractères définit par les 2èmes paranthèses)
Pour une URL de ce type /search/mot_cle, on aura juste une redirection 301 vers /search/mot–cle. Jusqu’ici tout va bien 🙂
Par contre, pour une URL de ce type: /search/mon_mot_cle, la règle de réécriture effectuera d’abord une redirection 301 vers /search/mot–cle_1, mais comme cette nouvelle URL contient encore un underscore, la règle s’exécutera à nouveau pour effectuer une redirection 301 vers /search/mot–cle–1: double 301.
Vous l’aurez compris, avec une suite de plusieurs termes séparés par des underscores dans mon URL, on peut rapidement arriver à une suites de quatre ou cinq redirections 301 qui se suivent, pas top…
La fausse bonne idée n°2
Vous êtes toujours là? Good!
La solution pourrait alors consister à créer plusieurs règles qui s’enchaînent avec toutes les possibilités (enfin en supposant qu’on peut avoir un max de 5 termes séparés par des underscores à réécrire dans les URL):
RewriteRule ^/search/([^_]*)_([^_]*)_([^_]*)_([^_]*)_(.*)$ /search/$1-$2-$3-$4-$5 [L,R=301] RewriteRule ^/search/([^_]*)_([^_]*)_([^_]*)_(.*)$ /search/$1-$2-$3-$4 [L,R=301] RewriteRule ^/search/([^_]*)_([^_]*)_(.*)$ /search/$1-$2-$3 [L,R=301] RewriteRule ^/search/([^_]*)_(.*)$ /search/$1-$2 [L,R=301]
Sur le principe, ça marcherait parfaitement, chaque règle correspondant à un nombre d’occurrences précis du caractère underscore. Mais voilà, il y a des points négatifs: ça fait des lignes en plus dans la configuration d’Apache (on complexifie le .htaccess) et on n’est pas certain de couvrir tous les cas (ex: 6 termes, ce qui rajouterait encore une ligne).
La solution la plus adaptée
La solution qui me paraît la plus adaptée consiste à utiliser le Flag [N] d’Apache qui reboucle au début du fichier .htaccess tant que la règle « matche ». Voici ce qu’on peut trouver à son sujet dans la documentation d’Apache:
Le drapeau [N] provoque un redémarrage du traitement des règles depuis le début, en utilisant le résultat du jeu de règles, sous réserve qu’il existe un point de démarrage ; à utiliser avec précautions car il peut provoquer un bouclage infini.
Le drapeau [Next] peut servir, par exemple, à remplacer de manière répétitive une chaîne de caractère ou une lettre dans une requête. Dans l’exemple suivant, chaque occurence de A sera remplacée par B dans la requête, et ceci jusqu’il n’y ait plus de A à remplacer.
C’est exactement ce qu’il nous faut! Il faudra par contre placer cette règle en tête de fichier pour éviter l’exécution des autres règles en boucle, ce qui alourdirait la charge serveur.
Voilà ce que donnerait notre règle qui n’effectuerait qu’une seule redirection 301 avec juste 2 lignes de code:
#Redirection 301 uniquement quand on a plus qu'un seul underscore RewriteRule ^/search/([^_]*)_([^_]*)$ /search/$1-$2 [R=301,L] #On supprime le premier underscore, puis on reboucle sur cette règle ([N]) #jusqu'à ce qu'il n'y ait plus qu'un seul underscore #la règle précédente prendra alors le relais RewriteRule ^/search/([^_]*)_(.+) /search/$1-$2 [N]
Voilà, j’espère que vous y voyez plus clair dans le remplacement de caractères via les règles de réecriture😉
Je ferais peut être un update de cet article pour la gestion de slashs multiples (suite à un échange avec @axenetwit)
Pour le teasing, j’en ai parlé à Sylvain. Du coup, on a fait un test pour voir si les URL avec de multiples slashs étaient indexées. Et bien non, Google les a ignorées.
Sinon merci pour la règle. 😉
Merci pour ce tutoriel « clé en main » qui permet de mettre en application directement ses regex. Les caractères spéciaux sont souvent une plaie et tout le monde n’a pas la patience de lire une doc. comme http://httpd.apache.org/docs/2.2/fr/rewrite/intro.html
Oh que c’est bien ça 🙂
Hop, signet !
Merci Aymeric.
Une des fonctions les plus puissantes permises par le fichier .htaccess est la réécriture « à la volée » des URL. Sur le site officiel Apache, le module mod_rewrite est présenté à raison comme le couteau suisse de la manipulation.