То, что я хотел бы сделать с mod_rewrite
в файле .htaccess
под Apache, выглядит следующим образом:
foo.txt
или foo / bar
, получено, проверьте, существует ли такой файл в подкаталоге public
, например public / foo.txt
или public / foo / bar
. Если это так, просто отобразите этот файл. mod_rewrite
в файле .htaccess
под Apache:
] foo.txt
или foo / bar
, проверьте, существует ли такой файл в подкаталоге public
, например public / foo.txt
или public / foo / bar
. Если это так, просто отобразите этот файл. mod_rewrite
в файле .htaccess
под Apache:
] foo.txt
или foo / bar
, проверьте, существует ли такой файл в подкаталоге public
, например public / foo.txt
или public / foo / bar
. Если это так, просто отобразите этот файл. public / foo / bar
. Если это так, просто отобразите этот файл. public / foo / bar
. Если это так, просто отобразите этот файл. index.php
Моя попытка решения заключалась в следующем:
<IfModule mod_rewrite.c>
RewriteEngine On
# Don't rewrite requests for files in the 'public' directory
RewriteRule ^(public)($|/) - [L]
# For all other files first check if they exist in 'public'
RewriteCond %{DOCUMENT_ROOT}/public%{REQUEST_URI} -f
RewriteRule ^ public%{REQUEST_URI} [L]
# Let 'index.php' handle everything else
RewriteRule . index.php [L]
</IfModule>
К сожалению, есть серьезный недостаток: он не работает в подкаталогах , т.е. когда .htaccess
и все другие файлы перемещаются из /
в / sub /
. В идеале, конечно, он работал бы в произвольных подпапках.
Кто-нибудь может помочь? Как я могу исправить .htaccess
, чтобы устранить этот недостаток?
У меня была похожая проблема, когда я хотел распространить веб-приложение, которое ведет себя так, как вы описываете: в определенном каталоге есть куча статических файлов, к которым можно получить доступ, как если бы они находились в корне веб-приложения (т. Е. Попытка /images/pic.png
получить изображение в public/images/pic.png
), а все остальное сопоставляется со сценарием контроллера.
Первая проблема, с которой я столкнулся, заключается в том, что -f
в RewriteCond
не работает с относительным путем - т.е. если строка "TestPattern" может быть разрешена в файл относительно каталога, где указано условие (используя .htaccess
), -f
по-прежнему будет возвращать «не соответствует»(1).
Поэтому нам нужно попытаться «понять», что такое префикс для каждого каталога, в котором находится файл .htaccess
, и mod_rewrite
на самом деле решает эту проблему для нас и гарантирует, что RewriteRule
всегда оценивается относительно префикса каталога .htaccess
файла - но, к сожалению, он не раскрывает эту информацию в любом случае, к которой RewriteCond
может получить доступ (они действительно должны позволить нам это иметь).
При этом, по-видимому, есть несколько странных вещей, которые вы можете сделать с RewriteCond
, чтобы заставить «CondPattern» выявить связь между %{REQUEST_URI}
и RewriteRule
- прочитайте ответы на этот вопрос обо всех странных вещах, которых вы можете достичь.
Но сокращая эти трюки только до поставленной задачи (получение -f
для соответствия правильному пути относительно .htaccess, независимо от того, где это может быть) мы получаем эту, довольно простую вещь:
RewriteEngine On
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2
RewriteCond %{DOCUMENT_ROOT}%1static/%2 -f
RewriteRule ^(.*)$ static/$1 [END]
RewriteRule . index.php [END,QSA]
Регулярное выражение в RewriteCond
очень ограничено тем, что оно не разрешается для переменных и захваченного текста, но оно может использовать обратные ссылки на себя, используя синтаксис
. Поэтому мы сначала создаем строку, состоящую из:
::
). RewriteRule
- это часть $1
: RewriteCond
может посмотреть на группу захвата целевого объекта RewriteRule
(2), поэтому мы захватываем весь ввод. Затем мы применяем регулярное выражение, которое объясняет связь между URI этого запроса и входом RewriteRule
- URI запроса состоит из двух частей (первая и вторая записи) где первый заканчивается разделителем /
, а второй идентичен тому, что появляется после разделителя ::
— 2
просто ссылается на второй захват в том же regexp и говорит, что он должен быть идентичным.
В результате мы разбили URI запроса на две группы захвата - первая - это локальный префикс для каждого каталога, которым mod_rewrite
пользуется конфиденциально, а вторая - локальный путь в этом каталоге, который мы хотим проверить. Второе условие использует %
для обозначения этих захватов, строящих абсолютный путь под корнем документа(3). Обратите внимание, что %1
захватывает как начальную, так и конечную косую черту префикса URI.
Наконец, обратите внимание, что я использую флаг END
вместо L
(последний), так как он быстрее и существует mod_rewrite
немедленно. Это позволяет мне опустить строку с RewriteRule ... - [Л]
, который существует только для того, чтобы остановить поведение L
, которое фактически не прекращает обработку: оно просто возвращается к началу или переписывает правила с новым URL-адресом. END
намного проще.
RewriteRule
и только затем проверяет, позволяют ли условия его применять. Alias
или аналогичные методы для сопоставления частей пространства URI сервера с другими местами, не находящимися под корнем документа. Обратитесь к документации по CONTEXT_DOCUMENT_ROOT
, чтобы узнать, как обойти эту проблему. Кажется, вы не хотите получить доступ к чему-либо за пределами папки / public? Если так, мне это кажется простым и без каких-либо переписываний (я надеюсь, что нет никаких причин, по которым вы действительно хотите, чтобы использовал mod_rewrite
!)
Если у вас есть причина использовать общую папку, вы можете использовать mod_rewrite
для перенаправления чего-либо, кроме index.php, в public / something, и по-прежнему использовать ErrorDocument для перенаправления на index.php.
Попробуйте использовать RewriteBase
при перемещении его во вложенную папку:
RewriteBase /subfolder/
# Rules
Этот набор правил мне подходит. Я пропустил проверку путей, которые запускают /public.[1233 visible. Если / public
не находится в корневом каталоге вашего документа, вы можете заменить% {DOCUMENT_ROOT} на путь на диске к каталогу / public. CONTEXT_DOCUMENT_ROOT
может содержать путь к каталогу содержимого для файла .htaccess
Если у вас нет того же файла в / public / public
, что и в / public
, RewriteCond
не будет соответствовать. Я избежал этой проблемы, используя свой эквивалент / public
в качестве корневого документа. Если вы не можете поместить index.php
в / public
, вы можете использовать Псевдоним
, чтобы получить к нему доступ, где он находится.
Ваш подход предполагает переписывание всего Матчи. Альтернативный набор правил, использующий ../ public
в качестве корня вашего документа, будет:
Псевдоним /index.php /var/www/index.php RewriteCond% {REQUEST_FILENAME}! -F RewriteCond% {REQUEST_FILENAME}! -D RewriteRule. /index.php [L]
Вы также можете обработать отсутствующие файлы с помощью специальной страницы ошибки 404.