Что делает RewriteBase и как его использовать?

Я пытаюсь изучить некоторые трюки .htaccess. Я наткнулся на директиву RewriteBase, но не смог заставить ее работать правильно.

Интересно, что конкретно эта директива делает и как ее использовать. Были некоторые обсуждения о RewriteBase в StackOverflow и документации Apache, но все же я не мог получить четкого ответа на мой вопрос.

Может ли кто-нибудь показать мне простой, но эффективный пример, где RewriteBase можно использовать?

Ответы

Ответ 1

В файле htaccess mod_rewrite работает аналогично контейнеру <Directory> или <Location>. и RewriteBase используется для предоставления относительной базы пути.

Например, скажем, что у вас есть эта структура папок:

root
 |-- subdir1
 |-- subdir2
       |-- subsubdir

Итак, вы можете получить доступ:

  • http://example.com/ (root)
  • http://example.com/subdir1 (subdir1)
  • http://example.com/subdir2 (subdir2)
  • http://example.com/subdir2/subsubdir (subsubdir)

URI, который отправляется через RewriteRule, относится к каталогу. Поэтому, если у вас есть:

RewriteRule ^(.*)$ - 

в корне, а запрос /a/b/c/d, тогда захваченный URI ($1) равен a/b/c/d. Но если правило находится в subdir2, а запрос /subdir2/e/f/g, то захваченный URI равен e/f/g. И если правило находится в subsubdir, а запрос /subdir2/subsubdir/x/y/z, то захваченный URI - x/y/z. Каталог, в котором находится правило, содержит эту часть, удаленную от URI. База rewrite не влияет на это, это просто то, как работает каждый каталог.

Что делает база перезаписи, предоставляет базу URL-пути (а не базу файлов) для любых относительных путей в целевом элементе правила. Поэтому скажите, что у вас есть это правило:

RewriteRule ^foo$ bar.php [L]

bar.php - относительный путь, а не:

RewriteRule ^foo$ /bar.php [L]

где /bar.php - абсолютный путь. Абсолютным путем всегда будет "корень" (в структуре каталогов выше). Это означает, что правило находится в "root", "subdir1" , "subsubdir" и т.д. Путь /bar.php всегда отображается на http://example.com/bar.php.

Но другое правило, с относительным путем, оно основано на каталоге, в котором находится правило. Поэтому, если

RewriteRule ^foo$ bar.php [L]

находится в "корне", и вы переходите к http://example.com/foo, вы получаете http://example.com/bar.php. Но если это правило находится в каталоге "subdir1" , и вы переходите к http://example.com/subdir1/foo, вам предоставляется http://example.com/subdir1/bar.php. и т.д. Это иногда работает, а иногда нет, как утверждает документация, оно должно требоваться для относительных путей, но большую часть времени оно, похоже, работает. За исключением случаев, когда вы перенаправляете (используя флаг R или неявно, потому что у вас есть http://host в целевом элементе правила). Это означает следующее правило:

RewriteRule ^foo$ bar.php [L,R]

если он находится в каталоге "subdir2", и вы переходите к http://example.com/subdir2/foo, mod_rewrite будет ошибочно относить путь как путь к файлу вместо URL-пути и из-за флага R, вы закончите перенаправляется на что-то вроде: http://example.com/var/www/localhost/htdocs/subdir1. Это, очевидно, не то, что вы хотите.

Здесь находится RewriteBase. Директива сообщает mod_rewrite, что добавить к началу каждого относительного пути. Поэтому, если у меня есть:

RewriteBase /blah/
RewriteRule ^foo$ bar.php [L]

и это правило находится в "subsubdir", переход на http://example.com/subdir2/subsubdir/foo будет действительно служить мне http://example.com/blah/bar.php. "Bar.php" добавляется к концу базы. На практике этот пример обычно не то, что вы хотите, потому что вы не можете иметь несколько оснований в одном контейнере каталога или файле htaccess.

В большинстве случаев он используется следующим образом:

RewriteBase /subdir1/
RewriteRule ^foo$ bar.php [L]

где эти правила будут находиться в каталоге "subdir1" и

RewriteBase /subdir2/subsubdir/
RewriteRule ^foo$ bar.php [L]

будет находиться в каталоге "subsubdir".

Это отчасти позволяет вам сделать ваши правила переносимыми, поэтому вы можете отбросить их в любой каталог и только изменить базу вместо целого ряда правил. Например, если у вас есть:

RewriteEngine On
RewriteRule ^foo$ /subdir1/bar.php [L]
RewriteRule ^blah1$ /subdir1/blah.php?id=1 [L]
RewriteRule ^blah2$ /subdir1/blah2.php [L]
...

так что переход в http://example.com/subdir1/foo будет служить http://example.com/subdir1/bar.php и т.д. И скажите, что вы решили перенести все эти файлы и правила в каталог "subsubdir". Вместо того чтобы менять каждый экземпляр /subdir1/ на /subdir2/subsubdir/, вы могли иметь только базу:

RewriteEngine On
RewriteBase /subdir1/
RewriteRule ^foo$ bar.php [L]
RewriteRule ^blah1$ blah.php?id=1 [L]
RewriteRule ^blah2$ blah2.php [L]
...

И тогда, когда вам нужно было переместить эти файлы и правила в другой каталог, просто измените базу:

RewriteBase /subdir2/subsubdir/

и что он.

Ответ 2

Ответ в 1 строке: Rewritebase устанавливает базовый путь rewriterule arg2.

Это буквально это. (поэтому он работает как html basehref, ⨕ за исключением того, что он полезен, так как часто в контексте перезаписи URL база по умолчанию [ . ] не нужна.)

Rewritebase упрощает обслуживание, если у вас есть несколько rewriterules. Действительно, если вы используете только одну строку rewriterule, тогда rewritebase практически бесполезен (так как вы можете просто переписать основанный URL).


Примечание

Конечно, вы можете полностью игнорировать rewritebase, используя только абсолютные пути для rewriterules.


связанные с

Ответ 3

RewriteBase позволяет вам настроить путь, к которому mod_rewrite автоматически RewriteBase к результату RewriteRule. Перезапись в контексте .htaccess выполняется относительно каталога, содержащего этот файл .htaccess. Непосредственный результат RewriteRule по-прежнему относится к каталогу, содержащему файл .htaccess, но тогда mod_rewrite корректирует этот результат, делая его относительно корня документа. RewriteBase позволяет вам изменить этот последний шаг, позволяя вам RewriteBase произвольный базовый путь, который предшествует немедленному результату RewriteRule, а не корню документа.

Для меня ключевым моментом в понимании директивы RewriteBase было то, что я понял, что mod_rewrite применяет RewriteBase к результатам RewriteRules, а не к их аргументам.

Обычная обработка RewriteRule в контексте файла .htaccess выглядит следующим образом:

  1. Создайте запрошенный путь относительно каталога, содержащего файл .htaccess. Если, например, URI - https://www.example.com/one/two/three, а файл .htaccess имеет путь /doc_root/one/.htaccess, то сгенерированный путь будет /two/three.
  2. Затем RewriteRules переписывают относительный путь сверху.
  3. Префикс полученного выше переписанного пути префикса к полному пути файловой системы к файлу .htaccess
  4. Удалите путь к корню документа из начала переписанного пути выше.

Этот процесс приводит к переписанному пути относительно корня документа.

При наличии директивы RewriteBase шаги 1,2 и 3 остаются прежними, изменяется только шаг 4. Вместо корня документа удаляется путь файловой системы к каталогу, содержащему файл .htaccess. Затем RewriteBase.

Пример:

  • Запрос - https://example.com/one/two/three/file.txt
  • Корень документа - /var/doc_root
  • Расположение htaccess - /var/doc_root/one/.htaccess
  • RewriteBase - /var/other_location/

Без RewriteBase в файле htaccess это обрабатывается как:

  1. Получить часть запрошенного пути относительно htaccess - /two/three/file.txt
  2. /four/rewritten.txt - /four/rewritten.txt
  3. Предварительный путь к файлу .htaccess - /var/do_root/one/four/rewritten.txt
  4. Удалите корень документа - one/four/rewritten.txt

С RewriteBase в файле .htaccess это обрабатывается как:

  1. Получить часть запрошенного пути относительно htaccess - /two/three/file.txt
  2. /four/rewritten.txt - /four/rewritten.txt
  3. Добавить RewriteBase - /var/other_location/four/rewritten.txt