Почему я получаю двойную косую черту в зависимости от того, где находится мой RewriteRule?

9

Я использую следующий код для перенаправления всех запросов www на не-www адреса:

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

Это прекрасно работает внутри файла .htaccess в корне моего сайта.
Например,
www.example.com -> example.com/
www.example.com/ -> example.com/
www.example.com/other_page -> example.com/other_page

Однако, если я перенесу этот же код в конфигурацию VirtualHost, переписанные URL-адреса содержат двойную косую черту.
www.example.com -> example.com//
www.example.com/ -> example.com//
www.example.com/other_page -> example.com//other_page

Я исправил это, удалив косую черту из правила перезаписи:

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

Но я не могу понять причину этого. Кто-нибудь знает почему?

davekaro
источник

Ответы:

10

Насколько я понимаю, в файлах .htaccess строка, которую обрабатывает mod_rewrite в вашем правиле, относится к каталогу, в котором находится файл .htaccess, поэтому в начале он не будет иметь /.

В записи VirtualHost строка, которую он обрабатывает, является абсолютной по отношению к корню сервера, и поэтому включает /.

Это делает для тонких различий в том, как работает mod_rewrite.

Вот кто-то с похожей проблемой и решением:

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

Это должно сработать в обоих случаях, если я правильно помню, что мне удалось сбежать:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^\/?(.*?)$ http://example.com/$1 [R=301,L]
Neobyte
источник
Спасибо! Теперь я понимаю, почему, по крайней мере. Однако почему-то это лучше, чем просто убрать / перед $ 1, как я показываю в моем первоначальном вопросе?
Давекаро
1
Не лучше и не хуже, это просто блок, который вы можете поменять между .htaccess VirtualHost без необходимости каждый раз редактировать его для обработки различий в контексте. Если ваш путь работает на вас, придерживайтесь его! :)
Neobyte
Ах да, ваш метод будет работать как в .htaccess, так и в VirtualHost. Это делает его лучше IMO :)
davekaro
4
У меня была та же проблема, что и у @davekaro, и я попробовал ваше решение. Последняя строка не работает для меня. RewriteRule ^/?(.*)$ http://example.com/$1 [R=301,L]сделал свое дело.
Кенни Рассчарт
2

Это происходит потому, что вы захватываете начальную косую черту (.*)и затем применяете другую косую черту перед ней в новом месте /$1. Этого не было раньше, потому что mod_rewrite ведет себя немного по-другому при работе в контексте для каждого каталога, в отличие от контекста для каждого сервера.

Вы можете избежать этого, опционально опередив косую черту. Кроме того, вы можете использовать RedirectMatch в пустом VirtualHost со своими избыточными доменами, что создает немного меньше обработки и может выглядеть чище.

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

Дэн Карли
источник
Ницца. Мне нравится подход RedirectMatch. Я, вероятно, пойду с этим, поскольку это действительно перенаправление, которое я хочу выполнить.
Давекаро
1

Я включаю этот пост для полноты.

Документация Apache объясняет, почему это происходит очень хорошо, и является причиной, по которой существует директива RewriteBase.

Простое включение директивы RewriteBase в ваш файл .htaccess позволит достичь желаемого результата.

Пример:

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

Из документации Apache 2.2 mod_rewrite:

Директива RewriteBase явно устанавливает базовый URL для перезаписей для каждого каталога.

Мое эмпирическое правило - почти всегда использовать 'RewriteBase' в файлах .htaccess, а не использовать его в конфигурации Apache.


источник
0

У меня не было времени для решения этой проблемы, поэтому просто переписать // в / :)

RewriteCond %{THE_REQUEST} //
RewriteRule ^(.*)$ http://domain.com [R=301,L]
user956584
источник