web-dev-qa-db-fra.com

Comment rediriger 301 vers un joli lien sans créer de boucle infinie dans .htaccess

Je suis en train de réécrire le fichier .htaccess pour rediriger les jolis liens vers les URL d'origine:

RewriteRule ^users/?$ /?status=users [NC,L,QSA]

qui redirige mon lien SEO/joli:

example.com/users

à la vraie URL

example.com/?status=users

Là encore, je veux n’importe quel moteur de recherche (ou qui que ce soit d’autre) qui essaie de

example.com/?status=users

être 301 redirigé vers le joli lien

example.com/users

Je sais que je pourrais obtenir la dernière partie en utilisant

RewriteCond %{QUERY_STRING} (^|&)status=users($|&)
RewriteRule ^$ /users? [L,R=301]

Mais je ne peux pas utiliser ces deux éléments ensemble, car il entre dans une boucle sans fin et le navigateur affiche "vous a redirigé trop de fois".

Je pense avoir compris le problème, mais quelle est la solution? Comment puis-je atteindre les deux?

2
nandu kk
RewriteCond %{QUERY_STRING} (^|&)status=users($|&)
RewriteRule ^$ /users? [L,R=301]

Vous avez juste besoin d'une condition (directive RewriteCond) supplémentaire sur votre redirection externe qui détecte s'il s'agit d'une demande directe/initiale de l'utilisateur, par opposition à - réécrit demande de votre autre directive de réécriture.

Une façon de faire est de vérifier le REDIRECT_STATUSvariable d'environnement. Ceci n'est pas défini sur la demande initiale, mais sur "200" (comme dans 200 OK) après la première réécriture réussie. Vous pouvez donc vérifier si REDIRECT_STATUS est vide afin de détecter la demande directe et d’empêcher une boucle de redirection.

Par exemple:

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} (^|&)status=users($|&)
RewriteRule ^$ /users? [L,R=301]

Une autre méthode consiste à vérifier par rapport à THE_REQUESTvariable serveur, qui contient la première ligne de la demande initiale et ne change pas lorsque l'URL est réécrite. Ainsi, lorsque vous demandez directement example.com/?status=users, THE_REQUEST contient une chaîne de la forme suivante:

GET /?status=users HTTP/1.1

Cela vous permettrait d’avoir juste un condition, au lieu de deux comme ci-dessus, au détriment d’une regex plus complexe. (L'implémentation est laissée comme un exercice pour le lecteur.)

2
MrWhite