У меня есть веб-сайт, который в настоящее время переходит со старой 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 для /folder
и все же перенаправить весь трафик из этой папки в корень.
Чтобы избежать цикла перенаправления, вам нужно различать прямой запрос на /public
подкаталог и запрос, который был внутренне переписанный к /public
подкаталог (что и делает ваша директива выше).
Есть несколько способов сделать это. Один из способов - проверить THE_REQUEST
серверная переменная, которая содержит заголовок начального запроса (например, GET /public/whatever HTTP/1.1
) как отправлено от клиента и не изменяется при перезаписи URL.
Попробуйте следующее ... как правило, внешние перенаправления должны выполняться до внутренних перезаписей, поэтому следующее правило должно находиться в верхней части .htaccess
файл в /public
подкаталог (не .htaccess
файл в корне документа):
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /public
RewriteRule (.*) /$1 [R=302,L]
Для любого непосредственный просьба начать /public/<whatever>
затем перенаправить на /<whatever>
. Предыдущие RewriteCond
Директива гарантирует, что обрабатываются только прямые запросы.
В RewriteRule
директива может сначала выглядеть немного странно (как будто она, возможно, перенаправляет на себя), но это потому, что RewriteRule
шаблон соответствует URL-пути меньше префикса каталога где .htaccess
файл находится. Итак, учитывая запрос на /public/<whatever>
, то $1
обратная ссылка только захватывает <whatever>
. Итак, перенаправляет обратно на /<whatever>
.
Обратите внимание, что в настоящее время это временное (302) перенаправление. Измените это на 301
только если вы уверены, что все в порядке. 301-файлы жестко кэшируются браузером, поэтому в случае ошибки тестирование может стать проблематичным.
смешивание
RedirectMatch
иRewriteRule
не смогли
Поскольку директивы принадлежат разным модулям (mod_alias vs mod_rewrite), они выполняются в разное время во время запроса, независимо от их очевидного порядка в файле конфигурации (mod_rewrite обычно запускается первым). Таким образом, смешивание этих директив действительно может привести к конфликтам. Тем не мение, RedirectMatch
не дает вам контроля, который требуется в этом случае.