Перенаправление всех страниц, кроме одной, на главную через .htaccess
Я только что преобразовал старый веб-сайт в одностраничный WordPress.
На старом сайте было несколько URL-адресов, теперь есть только 1: главная страница. Плюс еще одна страница с политикой конфиденциальности.
Поэтому я хотел бы перенаправить все URL-адреса, кроме того, который имеет slug "privacy", на главную страницу.
Вот что я пытаюсь сделать, но безуспешно:
#пользовательские перенаправления
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/privacy-policy/
RewriteRule (.*) http://www.mywebsite.com/$1 [R=301,L]
</IfModule>
# BEGIN WordPress (стандартные правила wp htaccess)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Происходит слишком много перенаправлений: все URL бесконечно перенаправляются сами на себя, почему?
было бы лучше (если возможно) использовать правило redirect вместо rewrite?
ОБНОВЛЕНИЕ
следуя предложениям из комментариев, я попробовал следующие пользовательские перенаправления (перед стандартными правилами WP):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/privacy-policy$
RewriteRule (.*) http://mywebsite.com/ [R=301,L]
</IfModule>
Но всё равно не работает
Проблемы
Получаю слишком много редиректов: все URL бесконечно перенаправляют сами на себя, почему?
Правила перезаписи Apache обрабатываются сверху вниз, поэтому ваше пользовательское правило перезаписи всегда выполняется первым. Флаг перенаправления R
указывает Apache сообщить браузеру выполнить новый запрос к изменённому URL вместо обслуживания цели перезаписи по текущему адресу, а флаг L
("last") говорит Apache игнорировать все последующие правила перезаписи. Таким образом, когда применяется ваше RewriteRule
, создаётся новый запрос и ваши правила снова обрабатываются с самого начала.
Ваше RewriteCond
указывает Apache обрабатывать последующее RewriteRule
, когда путь URI запроса не начинается с /privacy-policy
- поэтому практически каждый запрос приводит к перенаправлению до того, как другие правила в вашем .htaccess
могут быть хоть как-то оценены.
Как намекнул @MarkKaplun в комментариях, $1
- это обратная ссылка, которая заменяется частью совпавшего URI, содержащейся в первой "группе захвата" (первый набор скобок в шаблоне). Поскольку .*
буквально совпадает с любым количеством любых символов, в вашем RewriteRule
$1
заменяется всем путём URI.
По сути, ваши правила перезаписи:
RewriteCond %{REQUEST_URI} !^/privacy-policy/
RewriteRule (.*) http://www.mywebsite.com/$1 [R=301,L]
означают "Если URI не начинается с /privacy-policy/
, заставить веб-браузер отправить новый запрос к http://www.mywebsite.com/(исходный путь URI)
".
Для наглядности, предположим, вы перешли на http://www.mywebsite.com/blog/2015
; вот что происходит с каждым запросом:
/blog/2015
не начинается с/privacy-policy/
, сказать браузеру перейти наhttp://www.mywebsite.com/blog/2015
./blog/2015
не начинается с/privacy-policy/
, сказать браузеру перейти наhttp://www.mywebsite.com/blog/2015
./blog/2015
не начинается с/privacy-policy/
, сказать браузеру перейти наhttp://www.mywebsite.com/blog/2015
.- [...]
Удаление обратной ссылки $1
из RewriteRule
недостаточно, так как путь URI /
(или просто пустой) всё равно не соответствует началу с /privacy-policy/
, что приводит к такому поведению:
/blog/2015
не начинается с/privacy-policy/
, сказать браузеру перейти наhttp://www.mywebsite.com/
./
не начинается с/privacy-policy/
, сказать браузеру перейти наhttp://www.mywebsite.com/
./
не начинается с/privacy-policy/
, сказать браузеру перейти наhttp://www.mywebsite.com/
.- [...]
Вы можете проверить это поведение, посмотрев файлы журналов вашей установки Apache.
Решение
Если вы не планируете использовать стандартную маршрутизацию адресов WordPress, нет смысла оставлять стандартные правила перезаписи и добавлять новые поверх них. Настройте их под свои нужды вместо добавления сложности:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^(/|index\.php)$ /index.php? [L]
RewriteRule ^/?privacy-policy/?$ /index.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /? [L,R=301]
</IfModule>
Вкратце:
- .
RewriteRule ^(/|index\.php)$ /index.php? [L]
Если запрошены
/
илиindex.php
, обслуживатьindex.php
, но отбросить строку запроса (чтобы предотвратить изменение страниц через манипуляции с переменными запроса) и остановить обработку перезаписей. - .
RewriteRule ^/?privacy-policy/?$ /index.php [L]
Если запрошен
privacy-policy
(с ведущим или завершающим слешем или без), обслуживатьindex.php
и остановить обработку перезаписей. - .
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /? [L,R=301]
Если запрошенное имя файла не является файлом и не является директорией, совпасть с любым одиночным символом где угодно (чтобы применить правило независимо от URI) и сказать браузеру сделать новый запрос на
/
, отбросив строку запроса. Остановить обработку перезаписей.
Стоит отметить, что ваша задуманная логика, вероятно, вызовет множество неожиданных поведений - например, вы, скорее всего, не сможете получить доступ к административной панели. Также могут сломаться вложения. Но вышеприведённое как минимум даст хорошую отправную точку для изучения директив перезаписи.

спасибо @florian, но все еще не работает, он продолжает перенаправлять на ту же самую страницу, которую я пытаюсь открыть. Независимо от URL, он бесконечно перенаправляет сам на себя. PS: зачем расширение ".html"?

Извините, расширение '.html' действительно устарело. Странно, что у вас все еще происходит бесконечное перенаправление. Большинство браузеров сохраняют 301 редиректы в кеше. Я бы порекомендовал использовать Firebug для Firefox. Если вы используете FireBug, на вкладке Network в выпадающем меню есть опция отключения кеша браузера.
