У меня есть веб-сайт, который в настоящее время переносится со старой CMS на новую (Laravel). Только некоторые языки сайта были перенесены в Laravel. В общем, моя корневая папка vhost имеет что-то вроде этого:
[D] staticContentDirectory1
[D] staticContentDirectory2
...
[D] oldCmsDirectory1
[D] oldCmsDirectory2
...
[D] oldCmsDirectoryN
[D] public
[F] index-of-the-old-cms-still-in-use.php
У меня есть . htaccess
, который перенаправляет все, что не обрабатывается старой CMS или в каталоге статического содержимого, в Laravel и выглядит примерно так:
RewriteRule ^((?!staticContentDirectory1|staticContentDirectory2|public)(.*))$ public/$1 [L]
Существует также общедоступный .htaccess
из Laravel
Пока все работает отлично, и мы очень довольны результатом (с учетом начальных ограничений).
Однако мы обнаружили проблему. Каким-то образом Google удалось обнаружить, что / public
существует, и просканировать его, что привело к URL-адресу с / public /
внутри, который с тех пор создал / public / public /
URL-адреса (который, к счастью, возвращает ошибку 500 и позволяет избежать бесконечного количества URL-адресов).
Перед исправлением CMS и robots. txt
мы попытались исправить это, переписав / перенаправив трафик с / public
на /
.
Много чего было перепробовано, было много сбоев, почти все в бесконечном цикле редиректов.
Поскольку кажется, что каждый модуль Apache выполняет свои функции самостоятельно, смешивание RedirectMatch
и RewriteRule
не удалось. RewriteCond
и RewriteRule
либо были бесконечным перенаправлением, либо полностью игнорировались.
TL; DR: Я прошу помощи сейчас: как можно создать RewriteRule в / папку
и при этом перенаправить весь трафик из этой папки в корень.
Чтобы избежать цикла перенаправления, вам необходимо различать прямой запрос для подкаталога / public
и запрос, который был внутренне переписан в подкаталог / public
(что и делает ваша директива выше).
Есть несколько способов сделать это. Один из способов - проверить серверную переменную THE_REQUEST
, которая содержит заголовок начального запроса (например, GET / public / любой HTTP / 1.1
) как отправленный от клиента и не изменяется, когда URL-адрес перезаписывается.
Попробуйте следующее ... как правило, внешние перенаправления должны выполняться до внутренних перезаписей, поэтому следующее правило должно быть в верхней части файла .htaccess
в / public
подкаталог (не файл .htaccess
в корне документа):
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /public
RewriteRule (.*) /$1 [R=302,L]
Для любого прямого запроса, запускающего / public /
, затем перенаправьте на / <что угодно>
. Предыдущая директива RewriteCond
гарантирует, что обрабатываются только прямые запросы.
Директива RewriteRule
сначала может показаться немного странной (как будто она, возможно, перенаправляет на себя), но это поскольку шаблон RewriteRule
соответствует URL-пути за вычетом каталога-префикс того места, где находится файл .htaccess
. Таким образом, при запросе / public /
обратная ссылка $ 1
захватывает только
. Таким образом, выполняется перенаправление обратно на /
.
Обратите внимание, что в настоящее время это временное (302) перенаправление. Измените его на 301
, только если вы уверены, что все работает нормально. 301 жестко кэшируются браузером, поэтому при возникновении ошибки тестирование может стать проблематичным.
смешивание
RedirectMatch
иRewriteRule
не удалось
Поскольку директивы принадлежат разным модулям (mod_alias vs mod_rewrite), они выполняются в разное время во время запроса, независимо от их очевидного порядка в файле конфигурации (mod_rewrite обычно запускается первым). Таким образом, смешивание этих директив действительно может привести к конфликтам. Однако RedirectMatch
не дает вам контроля, который требуется в этом случае.