Aller au contenu
Serveur et .htaccess

Règles de redirection .htaccess WordPress : des 301 bien faites

Déplacez une URL sans perdre votre positionnement : quelle directive de redirection .htaccess utiliser sous WordPress, où placer les règles et comment les tester sans vous verrouiller dehors.

Publié

Vous déplacez une URL et vous voulez que l’ancienne conserve son positionnement ? Il vous faut une 301 dans .htaccess, placée là où WordPress ne l’effacera pas, écrite avec la bonne directive et pointant vers l’URL exacte que WordPress sert réellement. Ratez l’un de ces trois points et vous obtenez une chaîne de redirections, une boucle, ou une 500 qui vous verrouille hors de wp-admin.

La décision, la règle de placement et le test, dans cet ordre.

Quelle directive : Redirect, RedirectMatch ou RewriteRule

Deux modules Apache entrent en jeu et ils ne sont pas interchangeables.

Redirect (mod_alias) — un chemin connu vers une destination. La solution la plus simple qui fonctionne :

Redirect 301 /old-page/ https://example.com/new-page/

Deux comportements à connaître. La correspondance se fait sur un préfixe de chemin, pas sur une chaîne exacte : /old-page/ attrape donc aussi /old-page/anything/ et ajoute /anything/ à la destination. Et la chaîne de requête est reportée automatiquement.

RedirectMatch (mod_alias) — une expression régulière couvrant de nombreuses URL. C’est ainsi qu’on déplace une section entière :

RedirectMatch 301 ^/blog/(.*)$ https://example.com/articles/$1

Le groupe de capture (.*) devient $1 dans la destination, donc /blog/hello-world/ atterrit sur /articles/hello-world/. Notez la barre oblique initiale : les motifs de mod_alias correspondent au chemin complet de l’URL.

RewriteRule (mod_rewrite) — indispensable quand la redirection dépend d’une condition : le nom d’hôte, le protocole, une chaîne de requête, un agent utilisateur. Rien dans mod_alias ne sait évaluer cela.

RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

Dans un .htaccess par répertoire, le motif voit sa barre oblique initiale retirée — c’est pourquoi on écrit ^(.*)$ ici et ^/blog/ dans l’exemple mod_alias. Confondre les deux est de loin la raison la plus fréquente pour laquelle une règle copiée-collée ne fait discrètement rien.

Choisissez mod_alias par défaut. Ne sortez RewriteRule que lorsqu’une condition est nécessaire. Moins d’expressions régulières, moins de façons de se tromper.

Où les règles doivent aller

Les redirections personnalisées se placent au-dessus de la ligne # BEGIN WordPress. Pas à l’intérieur.

# --- custom redirects ---
Redirect 301 /old-page/ https://example.com/new-page/
RedirectMatch 301 ^/blog/(.*)$ https://example.com/articles/$1

# BEGIN WordPress
# The directives (lines) between "BEGIN WordPress" and "END WordPress" are
# dynamically generated, and should only be modified via WordPress filters.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Deux raisons indépendantes :

  1. WordPress réécrit son propre bloc. Enregistrer Réglages → Permaliens appelle flush_rewrite_rules(), qui jette tout ce qui se trouve entre les marqueurs et le régénère. Une règle placée à l’intérieur disparaît la prochaine fois que quelqu’un touche cet écran — peut-être des mois plus tard, sans que personne ne fasse le lien entre les deux événements.
  2. L’ordre décide du gagnant. Le bloc WordPress se termine par une règle fourre-tout qui envoie toute requête ne correspondant ni à un fichier ni à un répertoire vers index.php. Une RewriteRule placée après ne s’exécute jamais.

Une complication qu’il faut assumer : mod_alias et mod_rewrite ne s’exécutent pas réellement dans l’ordre du fichier. Apache traite mod_alias pendant la traduction d’URL et le mod_rewrite par répertoire plus tard, pendant la phase de fixup — une ligne Redirect peut donc l’emporter sur une RewriteRule qui apparaît plus haut dans le fichier. Si vous vous retrouvez à avoir besoin des deux sur des chemins qui se chevauchent, choisissez un module pour ce chemin et restez dedans. Déboguer un conflit mod_alias contre mod_rewrite ne vaut pas l’heure que ça coûte.

Les barres obliques finales

La redirection canonique propre à WordPress ajoute une barre oblique finale à la plupart des permaliens. Donc ceci :

Redirect 301 /old-page/ https://example.com/new-page

produit deux sauts — votre 301 vers l’URL sans barre, puis la 301 de WordPress qui ajoute la barre. Les chaînes transmettent toujours les signaux de référencement, mais elles gaspillent le budget d’exploration et ajoutent un aller-retour pour chaque visiteur.

Chargez d’abord la destination dans un navigateur, copiez l’URL exactement telle qu’elle se stabilise dans la barre d’adresse, et utilisez celle-là. Si votre structure de permaliens se termine par .html ou n’a pas de barre finale, alignez-vous là-dessus. Il n’y a pas de réponse universellement correcte ici, seulement « faites correspondre ce que WordPress sert ».

Tester sans se verrouiller dehors

.htaccess est lu à chaque requête. Une erreur de syntaxe renvoie une 500 sur tout le site, wp-admin compris : la voie de secours doit donc exister avant que vous en ayez besoin.

Sauvegardez d’abord le fichier. En SSH :

cp /path/to/wordpress/.htaccess /path/to/wordpress/.htaccess.bak

Si le site part en 500, replacez le fichier de secours par-dessus le fichier cassé et le site revient immédiatement. Gardez une session SFTP déjà ouverte dans une autre fenêtre — se connecter de zéro pendant que le site est à terre, c’est là que la panique commence. Notez que apachectl configtest n’analyse pas .htaccess : il signalera donc une configuration saine pendant que votre site est mort.

Testez avec curl, pas avec un navigateur. Les navigateurs mettent les réponses 301 en cache très agressivement et vous montreront volontiers le résultat d’hier :

curl -sI https://example.com/old-page/ | head -n 5

Lisez deux choses : la ligne de statut doit indiquer 301, et l’en-tête Location: doit être exactement l’URL finale. Pour voir toute la chaîne, suivez-la :

curl -sIL https://example.com/old-page/ | grep -E '^(HTTP|Location)'

Plus d’une ligne HTTP/1.1 301 signifie que vous avez construit une chaîne. Plus de cinq environ signifie que vous avez construit une boucle, et curl s’arrêtera pour vous le dire.

Utilisez une 302 tant que vous n’êtes pas sûr. Une 302 n’est pas mise en cache de la même manière, donc une erreur se corrige en quelques secondes. Passez en 301 une fois que curl affiche la destination voulue. Cela ne coûte rien et a sauvé plus de sites que n’importe quelle autre habitude de cet article.

Si une règle semble ne rien faire du tout, vérifiez qu’Apache lit seulement le fichier. AllowOverride None sur le répertoire fait qu’Apache ignore complètement .htaccess, et nginx l’ignore totalement — vérifiez l’en-tête Server: avec curl -I avant de déboguer des expressions régulières. Pour assembler le bloc avec la syntaxe adaptée à votre version d’Apache et à votre chemin d’installation, utilisez le générateur de .htaccess WordPress.

Quand ne pas utiliser .htaccess du tout

Pour une poignée de redirections que les rédacteurs doivent gérer eux-mêmes, une extension de redirection stockant les règles en base de données est le meilleur outil — elle survit aux migrations d’hébergement et ne demande pas de SSH. Le compromis est réel : PHP doit démarrer pour servir la redirection, ce qui est plus lent qu’Apache répondant directement.

Utilisez .htaccess pour les déplacements structurels et définitifs — un changement de domaine, le renommage d’une section, le forçage de https ou de www. Utilisez une extension pour les redirections éditoriales ponctuelles. Faire les deux ne pose pas de problème tant que vous savez quelle couche possède quelle URL, car une redirection définie à deux endroits est un bug qui attend son mauvais après-midi.

FAQ

Questions

Où placer les redirections personnalisées dans le fichier .htaccess de WordPress ?

Au-dessus de la ligne # BEGIN WordPress, jamais entre les marqueurs. WordPress régénère tout ce qui se trouve entre ces marqueurs dès que quelqu'un enregistre l'écran des permaliens, donc une règle placée à l'intérieur est supprimée sans avertissement. L'emplacement compte aussi pour l'ordre : le bloc WordPress se termine par une règle fourre-tout qui envoie les requêtes non traitées vers index.php.

Faut-il utiliser Redirect, RedirectMatch ou RewriteRule pour une 301 ?

Utilisez Redirect pour un chemin unique connu, RedirectMatch quand un seul motif couvre de nombreuses URL, et RewriteRule quand la redirection dépend d'une condition telle que le nom d'hôte, le protocole ou la chaîne de requête. Redirect et RedirectMatch viennent de mod_alias et sont plus simples. RewriteRule vient de mod_rewrite et c'est la seule capable d'évaluer des conditions.

Pourquoi ma redirection .htaccess provoque-t-elle une boucle de redirection ?

En général la destination correspond encore à la règle qui y a envoyé le visiteur, donc la règle se déclenche indéfiniment. L'autre cause fréquente est le forçage de https derrière un répartiteur de charge ou un CDN, où le serveur voit du http simple sur chaque requête même si le visiteur est déjà en https. Testez plutôt l'en-tête X-Forwarded-Proto.

La barre oblique finale a-t-elle une importance dans une redirection WordPress ?

Oui. La redirection canonique de WordPress ajoute une barre oblique finale à la plupart des permaliens, donc pointer une 301 vers une URL sans barre produit deux sauts au lieu d'un. Les redirections chaînées transmettent toujours les signaux de référencement, mais elles gaspillent le budget d'exploration et ralentissent le visiteur. Faites correspondre exactement l'URL finale servie par WordPress, barre comprise.

Comment tester une redirection .htaccess sans casser mon site ?

Lancez curl avec l'option en-têtes seuls sur l'ancienne URL et lisez le code de statut et l'en-tête Location avant de faire confiance à un navigateur. Les navigateurs mettent les réponses 301 en cache de façon agressive et vous montreront un résultat périmé. Conservez d'abord une copie du fichier fonctionnel, car une erreur de syntaxe dans .htaccess renvoie une 500 sur toutes les pages, wp-admin compris.

Pourquoi tout mon site a-t-il renvoyé une erreur 500 après l'ajout d'une redirection ?

Une seule directive mal formée dans .htaccess met hors service toutes les URL sous ce répertoire, administration incluse. Les causes courantes sont un bloc IfModule non fermé, une ligne RewriteEngine On manquante, ou les syntaxes d'accès d'Apache 2.2 et 2.4 mélangées dans un même fichier. Supprimez le dernier bloc ajouté et rechargez pour confirmer.