Как RewriteBase работает в .htaccess - PullRequest
215 голосов
/ 01 апреля 2009

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

RewriteBase /

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

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

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

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

Спасибо

Ответы [ 8 ]

96 голосов
/ 01 апреля 2009

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

Вы можете использовать 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.

71 голосов
/ 13 января 2015

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

  • Использование RewriteBase, как это ...

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

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

    RewriteRule a\.html b.html
    

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

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

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

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

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



Цитата из Отличный исчерпывающий ответ Джона Линя здесь :

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

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

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

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

URI, который отправляется через 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]

в "sububdir", переход на 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]

будет в каталоге "sububdir".

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

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/

и все.

41 голосов
/ 20 января 2012

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

RewriteBase myfolder

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

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

23 голосов
/ 13 декабря 2010

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

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

19 голосов
/ 01 декабря 2012

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

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

RewriteBase /
# RewriteBase /dev_folder/

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

# RewriteBase /
RewriteBase /dev_folder/
18 голосов
/ 24 марта 2013

Самое ясное объяснение, которое я нашел, было не в текущих документах 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 содержит «подробную информацию о внутренних этапах обработки».

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

3 голосов
/ 16 октября 2011

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

RewriteBase /
2 голосов
/ 13 февраля 2013

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

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

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

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

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

...