Pourquoi est-ce que j'obtiens une double barre oblique en fonction de l'emplacement de ma RewriteRule?

9

J'utilise le code suivant pour diriger toutes les demandes www vers des URL non www:

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

Cela fonctionne très bien à l'intérieur d'un fichier .htaccess à la racine de mon site Web.
Par exemple,
www.example.com -> example.com/
www.example.com/ -> example.com/
www.example.com/other_page -> example.com/other_page

Cependant, si je déplace ce même code dans ma configuration VirtualHost, les URL réécrites contiennent une double barre oblique.
www.example.com -> example.com//
www.example.com/ -> example.com//
www.example.com/other_page -> example.com//other_page

Je l'ai corrigé en supprimant la barre oblique de la règle de réécriture:

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

Mais je ne peux pas comprendre la raison de cela. Quelqu'un sait pourquoi?

davekaro
la source

Réponses:

10

Si je comprends bien, dans les fichiers .htaccess, la chaîne que mod_rewrite traite dans votre règle est relative au répertoire dans lequel se trouve le fichier .htaccess, donc il n'aura pas de / au début.

Dans l'entrée VirtualHost, la chaîne qu'il traite est absolue à la racine du serveur, et inclut donc le /.

Cela crée de subtiles différences dans le fonctionnement de mod_rewrite.

Voici quelqu'un avec un problème similaire et une solution:

http://forum.modrewrite.com/viewtopic.php?p=56322&sid=77f72967f59200b5b5de174440234c3a

Cela devrait fonctionner dans les deux cas, en supposant que je me souvienne de ma fuite correctement:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^\/?(.*?)$ http://example.com/$1 [R=301,L]
Neobyte
la source
Merci! Maintenant je comprends pourquoi, au moins. Cependant, est-ce mieux pour une raison quelconque que de simplement supprimer le / avant le $ 1 comme je le montre dans ma question d'origine?
davekaro
1
Pas mieux ni pire, c'est juste un bloc que vous pouvez permuter entre .htaccess de VirtualHost sans avoir à le modifier à chaque fois pour gérer les différences de contexte. Si votre chemin vous convient, respectez-le! :)
Neobyte
Oh c'est vrai - votre méthode fonctionnera à la fois dans .htaccess et VirtualHost. Cela rend mieux l'OMI :)
davekaro
4
J'ai eu exactement le même problème que @davekaro et j'ai essayé votre solution. La dernière ligne n'a pas fonctionné pour moi. RewriteRule ^/?(.*)$ http://example.com/$1 [R=301,L]a fait l'affaire.
Kenny Rasschaert
2

Cela se produit parce que vous capturez une barre oblique initiale avec (.*)puis appliquez une autre barre oblique avant dans le nouvel emplacement /$1. Cela ne s'était pas produit auparavant car mod_rewrite se comporte légèrement différemment lorsqu'il fonctionne dans un contexte par répertoire par opposition à un contexte par serveur.

Vous pouvez éviter cela en anticipant éventuellement la barre oblique. De plus, vous pouvez utiliser RedirectMatch dans un VirtualHost vide avec vos domaines excédentaires, ce qui crée un peu moins de traitement et peut sembler plus propre.

<VirtualHost *>
ServerName example.com
ServerAlias other.example.com
..
RedirectMatch permanent ^/?(.*) http://example.com/$1
</VirtualHost>

Dan Carley
la source
Agréable. J'aime l'approche RedirectMatch. J'irai probablement avec cela car c'est vraiment une redirection que je veux accomplir.
davekaro
1

J'inclus ce post pour être complet.

La documentation Apache explique pourquoi ce problème se produit très bien et est la raison pour laquelle la directive «RewriteBase» existe.

Le simple fait d'inclure la directive «RewriteBase» dans votre fichier .htaccess devrait atteindre le résultat souhaité.

Exemple:

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

Dans la documentation Apache 2.2 mod_rewrite:

La directive RewriteBase définit explicitement l'URL de base pour les réécritures par répertoire.

Ma règle d'or est d'utiliser presque toujours «RewriteBase» dans les fichiers .htaccess, et de ne pas l'utiliser dans la configuration Apache.


la source
0

Je n'ai pas eu le temps de gérer ce problème, il suffit donc de réécrire // dans / :)

RewriteCond %{THE_REQUEST} //
RewriteRule ^(.*)$ http://domain.com [R=301,L]
user956584
la source