Чому я отримую подвійну кінцеву косу рису залежно від того, де знаходиться мій RewriteRule?


9

Я використовую такий код, щоб спрямувати всі запити 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]

Але я не можу зрозуміти причину цього. Хтось знає, чому?

Відповіді:


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]

Дякую! Тепер я розумію, чому, принаймні. Однак чи є це чомусь краще, ніж просто видалити / до $ 1, як я показую в своєму первісному запитанні?
davekaro

1
Ні кращого, ні гіршого, це просто блок, на який ви можете переключатися між. Якщо ваш шлях працює для вас, дотримуйтесь цього! :)
Neobyte

О, це правильно - ваш метод буде працювати як у .htaccess, так і в VirtualHost. Це робить ІМО кращим :)
dakakaro

4
У мене була та сама проблема, що і в @davekaro, і я спробував ваше рішення. Останній рядок для мене не працював. RewriteRule ^/?(.*)$ http://example.com/$1 [R=301,L]зробив трюк.
Kenny Rasschaert

2

Це відбувається тому, що ви зафіксували початкову косу рису, (.*)а потім застосуєте іншу косу рису перед цим у новому місці /$1. Це не відбулося раніше, оскільки mod_rewrite поводиться дещо інакше при роботі в контексті для каталогу, на відміну від контексту на сервері.

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

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


Приємно. Мені подобається підхід RedirectMatch. Я, мабуть, піду з цим, оскільки це дійсно є переспрямуванням, яке я хочу досягти.
davekaro

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]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.