Как RewriteBase работает в .htaccess

227

Я видел это в нескольких .htaccessпримерах

RewriteBase /

Похоже, что-то похоже на функциональность <base href="">HTML.

Я полагаю, что он может автоматически добавлять значение к началу RewriteRuleоператоров (возможно, без косой черты)?

Я не мог заставить это работать должным образом. Я думаю, что его использование может пригодиться для переносимости сайта, так как у меня часто есть сервер разработки, который отличается от производственного сервера. Мой текущий метод оставляет мне удаление частей из моих RewriteRuleзаявлений.

Может кто-нибудь объяснить мне кратко, как это реализовать?

Спасибо

Алекс
источник
8
Руководство: httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritebase
Салман фон Аббас
RewriteBase работает только в каталоге или в контексте .htaccess ... обратитесь к контексту за предоставленной ссылкой @SalmanPK.
Эдди Б
1
Смотрите этот ответ для хорошего описания. stackoverflow.com/a/2137593/292060
goodeye
1
Это более подробный ответ: stackoverflow.com/a/21348047/632951
Pacerier
Это однострочный ответ: stackoverflow.com/a/46541685/632951
Pacerier

Ответы:

102

По моим собственным словам, после прочтения документов и экспериментов:

Вы можете использовать, RewriteBaseчтобы обеспечить базу для ваших переписывает. Учти это

# invoke rewrite engine
    RewriteEngine On
    RewriteBase /~new/

# add trailing slash if missing
    rewriteRule ^(([a-z0-9\-]+/)*[a-z0-9\-]+)$ $1/ [NC,R=301,L]

Это реальное правило, которое я использовал, чтобы убедиться, что URL-адреса имеют косую черту. Это преобразует

http://www.example.com/~new/page

в

http://www.example.com/~new/page/

Имея RewriteBaseтам, вы делаете относительный путь от RewriteBaseпараметра.

Алекс
источник
10
«Отойти от параметра RewriteBase» - вы имели в виду параметр rewriteRule? :)
Kissaki
1
Я хочу прояснить некоторые детали htaccess. ReWriteBase устанавливает его для всех правил в htaccess, следующих за его объявлением? есть ли способ его сбросить, можно ли его сбросить?
Деймон
3
@ Kissaki: Нет, $1совпадает с шаблоном RewriteRule , заключенным в скобки, но относительный путь для подстановки определяется параметром RewriteBase. Итак, итоговая замена есть /~new/$1/.
MrWhite
3
@ Damon: см. Этот вопрос о нескольких RewriteBaseдирективах. Короче говоря, вы не можете иметь больше одного - я думаю, что последняя RewriteBase директива побеждает и влияет на весь файл .htaccess.
MrWhite
24
-1; этот ответ, похоже, помог другим, но совершенно непрозрачен для меня. Я мог бы догадаться , что «Вы можете использовать , RewriteBaseчтобы обеспечить основу для переписывания» - это в значительной степени просто перестановка слов - но я понятия не имею , что такое «база» находится в этом контексте, ни то, как смысл приведенный вами пример будет отличаться, если RewriteBaseстрока будет удалена. Прочь к руководству, я иду ...
Марк Amery
89

RewriteBaseприменяется только к мишени о наличии относительного правила перезаписи.

  • Используя RewriteBase, как это ...

    RewriteBase /folder/
    RewriteRule a\.html b.html
    
  • по сути то же самое, что и ...

    RewriteRule a\.html /folder/b.html
    
  • Но когда файл .htaccess находится внутри, /folder/это также указывает на ту же цель:

    RewriteRule a\.html b.html
    

Хотя документы подразумевают всегда использование a RewriteBase, Apache обычно правильно определяет его для путей в DocumentRoot, если только:

  • Вы используете Aliasдирективы

  • Вы используете правила перезаписи .htaccess для выполнения перенаправления HTTP (а не просто перезаписи без вывода сообщений) на относительные URL

В этих случаях вы можете обнаружить, что вам нужно указать RewriteBase.

Тем не менее, поскольку это непонятная директива, обычно лучше просто указывать абсолютные (иначе называемые «коренные родственники») URI в целях перезаписи. Другие разработчики, читающие ваши правила, поймут это легче.



Цитата из превосходного подробного ответа Джона Линя здесь :

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

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

DocumentRoot
|-- subdir1
`-- subdir2
    `-- subsubdir

Таким образом, вы можете получить доступ к:

  • http://example.com/ (Корень)
  • http://example.com/subdir1 (Subdir1)
  • http://example.com/subdir2 (Subdir2)
  • http://example.com/subdir2/subsubdir (Subsubdir)

URI, который отправляется через a, RewriteRuleотносится к каталогу, содержащему файл htaccess. Так что если у вас есть:

RewriteRule ^(.*)$ - 
  • В корне htaccess и запрос есть /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. База переписывания не влияет на это, это просто, как работает для каждого каталога.

Что делает база перезаписи , так это предоставляет базу 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]

в «субсубдире», собираясь на 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/

и это все.

Simon East
источник
По мне я скучала RewriteEngine On. Например, нет необходимости в 1 и 1, но это требуется на моем выделенном сервере.
Portekoi
41

AFAIK, RewriteBase используется только для исправления случаев, когда mod_rewrite запускается в .htaccessфайле, а не в корне сайта, и угадывает неправильный веб-путь (в отличие от пути файловой системы) для папки, в которой он запущен. Так что если у вас есть RewriteRule в .htaccess в папке, которая отображается на http://example.com/myfolderвас, можно использовать:

RewriteBase myfolder

Если mod_rewrite не работает правильно.

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

rjmunro
источник
2
Должен ли он заканчиваться косой чертой?
Pacerier
@self, Нет. Проверено и объяснено здесь: stackoverflow.com/a/11443194/632951
Pacerier
23

RewriteBase полезен только в ситуациях, когда вы можете поместить только .htaccess в корень вашего сайта. В противном случае, возможно, вам лучше разместить свои файлы .htaccess в разных каталогах вашего сайта и полностью пропустить директиву RewriteBase.

В последнее время для сложных сайтов я убираю их, потому что это усложняет развертывание файлов из тестирования, чтобы жить еще на один шаг.

Томас Хантер II
источник
22
Хотя это может быть хорошим советом, это вовсе не ответ на вопрос. Таким образом, он должен был быть комментарием к вопросу, не иметь (как много) голосов и определенно не приниматься как «ответ».
Киссаки
3
«лучше размещать разные файлы .htaccess в разных каталогах» - я не уверен, что это хороший совет? Наличие файлов .htaccess, разбросанных по всему сайту, может сделать отладку / обслуживание кошмаром. Я бы сказал, что лучше иметь один файл .htaccess в корне вашего сайта.
MrWhite
1
@ w3d Существует также вопрос синхронизации: каждый раз, когда осуществляется доступ к подкаталогу, несколько файлов .htaccess анализируются (от корневого до текущего подкаталога). Наличие большого количества файлов может снизить скорость общего ответа на запрос, в отличие от одного файла в корне, даже если он содержит много правил ..
Erenor Paz
19

Когда я разрабатываю, он находится в другом домене в папке. Когда я беру сайт вживую, эта папка больше не существует. Использование RewriteBase позволяет мне использовать один и тот же файл .htaccess в обеих средах.

Когда живешь:

RewriteBase /
# RewriteBase /dev_folder/

При разработке:

# RewriteBase /
RewriteBase /dev_folder/
user1669830
источник
4
Я уверен, что это не всегда будет работать. Что если вы используете %{REQUEST_URI}в RewriteCondдирективе, например?
MrWhite
1
@ user1669830, если у вас есть только один rewriterule, вы могли бы просто добавить базу в rewriterule
rewriterule
18

Самое ясное объяснение, которое я нашел, было не в текущих документах Apache 2.4, а в версии 2.0 .

#  /abc/def/.htaccess -- per-dir config file for directory /abc/def
#  Remember: /abc/def is the physical path of /xyz, i.e., the server
#            has a 'Alias /xyz /abc/def' directive e.g.

RewriteEngine On

#  let the server know that we were reached via /xyz and not
#  via the physical path prefix /abc/def
RewriteBase   /xyz

Как это работает? Для вас, apache-хакеров, этот документ 2.0 содержит «подробную информацию о внутренних этапах обработки».

Извлеченный урок: хотя мы должны быть знакомы с «текущим», драгоценные камни можно найти в летописях.

DWB
источник
3

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

RewriteBase /
Сандип Гоял
источник
2

Я считаю, что этот отрывок из документации Apache хорошо дополняет предыдущие ответы:

Эта директива требуется, когда вы используете относительный путь в подстановке в контексте для каждого каталога (htaccess), если не выполняется одно из следующих условий:

  • Первоначальный запрос и подстановка находятся под DocumentRoot (в отличие от достижимого другими средствами, такими как Alias).

  • Путь файловой системы к каталогу, содержащему RewriteRule, с суффиксом относительной подстановки, также действителен как URL-путь на сервере (это редко).

Как уже упоминалось ранее, в других контекстах полезно сокращать правило. Кроме того, как уже упоминалось ранее, вы можете добиться того же, поместив файл htaccess в подкаталог.

Алекс
источник