Установите RewriteBase на текущий путь папки динамически

Есть ли способ установить RewriteBase в путь к текущей папке (папке, в которой находится файл .htaccess) относительно корня хоста?

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

Обновить:

Например:

webroot

 - sub_directory
 - cms
 - .htaccess

в этом случае я должен написать в htaccess: RewriteBase/

и если я перемещаю htaccess внутри sub_directory, я должен изменить RewriteBase на:

RewriteBase/sub_directory/

Поэтому я хочу что-то вроде

RewriteBase/%{current_folder}/

Ответы

Ответ 1

Вот один из способов захватить RewriteBase в переменной среды, которую вы затем можете использовать в своих других правилах перезаписи:

RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]

Затем вы можете использовать %{ENV:BASE} в своих правилах для обозначения RewriteBase.

Объяснение:

Это правило работает, сравнивая REQUEST_URI с URL-адресом, который видит RewriteRule, который является REQUEST_URI с ведущим RewriteBase удаленным. Разница заключается в RewriteBase и помещается в %{ENV:BASE}.

  • В RewriteCond LHS (тестовая строка) может использовать обратные ссылки, например. $1, $2 OR %1, %2 и т.д., но сторона RHS, т.е. строка условия не может использовать эти переменные $1, $2 OR %1, %2.
  • В части состояния RHS только обратная ссылка, которую мы можем использовать, - это внутренние обратные ссылки, т.е. группы, которые мы захватили в этом условии. Они обозначаются символами \1, \2 и т.д.
  • В RewriteCond первая захваченная группа (.*?/). Он будет представлен внутренней обратной ссылкой `\ 1.
  • Как вы можете отметить, что это правило в основном находит RewriteBase динамически, сравнивая %{REQUEST_URI} и $1. Примером %{REQUEST_URI} будет /directory/foobar.php и пример $1 для того же примера URI будет foobar.php. ^(.*?/)(.*)::\2$ помещает разницу в 1-ю захваченную группу %1 или \1. В нашем примере он заполнит %1 или \1 значением /directory/, которое будет использоваться позже при настройке переменной env %{BASE} i.e. E=BASE:%1.

Ответ 3

Основываясь на anubhava answer и Jon Lin's, вот что я только что придумал для себя (гавань 't использовал это в производстве и не тестировал это еще раз).

Используйте этот пример URL, где .htaccess находится в текущей папке:

http://localhost/path_to/current_folder/misc/subdir/file.xyz

Файловая система: /var/www/webroot/path_to/current_folder/.htaccess

Options +FollowSymLinks
RewriteEngine On
RewriteBase /

RewriteCond %{ENV:SUBPATH} ^$  # Check if variable is empty. If it is, process the next rule to set it.
RewriteRule ^(.*)$ - [ENV=SUBPATH:$1]
# SUBPATH is set to 'misc/subdir/file.xyz'

RewriteCond %{ENV:CWD} ^$
RewriteCond %{ENV:SUBPATH}::%{REQUEST_URI} ^(.*)::(.*?)\1$
RewriteRule ^ - [ENV=CWD:%2]
# CWD is set to '/path_to/current_folder/'

RewriteCond %{ENV:FILENAME} ^$
RewriteCond %{REQUEST_URI} ^.*/(.*)$
RewriteRule ^ - [ENV=FILENAME:%1]
# FILENAME is set to 'file.xyz'

# Check if /var/www/webroot/path_to/current_folder/misc/subdir/file.xyz exists.
# -f checks if a file exists, -d checks for a directory.
# If it exists, rewrite to /path_to/current_folder/misc/subdir/file.xyz and stop processing rules.
RewriteCond %{ENV:SUBPATH} ^.+$  # Ensure SUBPATH is not empty
RewriteCond %{DOCUMENT_ROOT}%{ENV:CWD}%{ENV:SUBPATH} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{ENV:CWD}%{ENV:SUBPATH} -d
RewriteRule ^.*$ %{ENV:CWD}%{ENV:SUBPATH} [END]

# Check if /var/www/webroot/path_to/current_folder/file.xyz exists.
# If it exists, rewrite to /path_to/current_folder/file.xyz and stop processing rules.
RewriteCond %{ENV:FILENAME} ^.+$
RewriteCond %{DOCUMENT_ROOT}%{ENV:CWD}%{ENV:FILENAME} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{ENV:CWD}%{ENV:FILENAME} -d
RewriteRule ^.*$ %{ENV:CWD}%{ENV:FILENAME} [END]

# Else, rewrite to /path_to/current_folder/index.html and stop processing rules.
RewriteRule ^.*$ %{ENV:CWD}index.html [END]

Вы можете просмотреть сведения о том, что происходит для вас, используя LogLevel alert rewrite:trace6 в httpd.conf в apache, а затем посмотрите в error.log.

Здесь немного больше пояснений на следующие две строки, которые я все еще немного запутал.

RewriteCond %{ENV:SUBPATH}::%{REQUEST_URI} ^(.*)::(.*?)\1$
RewriteRule ^ - [ENV=CWD:%2]

Во-первых, двойной двоеточие :: не является каким-либо оператором; это просто произвольный разделитель. RewriteCond расширяет TestString %{ENV:SUBPATH}::%{REQUEST_URI} до следующего:

misc/subdir/file.xyz::/path_to/current_folder/misc/subdir/file.xyz

Затем наш CondPattern ^(.*)::(.*?)\1$:

  • ^(.*):: соответствует misc/subdir/file.xyz::
  • \1 - первая группа захвата, misc/subdir/file.xyz
  • (.*?)\1$ становится (.*?)misc/subdir/file.xyz$
  • Таким образом, наша вторая группа захвата (.*?) соответствует оставшемуся /path_to/current_folder/

И наш RewriteRule устанавливает CWD в %2, который является второй группой захвата CondPattern.