Я использую следующий код, чтобы направлять все запросы www на URL-адреса без 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]
Но я не могу понять причину этого. Кто-нибудь знает почему?
Насколько я понимаю, в файлах .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]
Это происходит из-за того, что вы захватываете начальную косую черту с помощью (.*)
а затем применив еще одну косую черту перед ним в новом месте /$1
. Раньше этого не происходило, потому что mod_rewrite ведет себя немного иначе при работе в контексте каталога, а не в контексте сервера.
Вы можете избежать этого, опционально прервав косую черту. Кроме того, вы можете использовать RedirectMatch в пустом VirtualHost с вашими избыточными доменами, что немного меньше обрабатывает и может выглядеть чище.
<VirtualHost *>
ServerName example.com
ServerAlias other.example.com
..
RedirectMatch permanent ^/?(.*) http://example.com/$1
</VirtualHost>
Я включаю этот пост для полноты картины.
В Документация 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.
У меня не было времени разбираться с этой проблемой, поэтому просто перепишите // на / :)
RewriteCond %{THE_REQUEST} //
RewriteRule ^(.*)$ http://domain.com [R=301,L]