Установите 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
.
Ответ 2
Я думаю, что принятое решение не сработало, но это сработало: http://www.zeilenwechsel.de/it/articles/8/Using-mod_rewrite-in-.htaccess-files-without-knowing-the-RewriteBase.html
Короче:
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond $0#%{REQUEST_URI} ([^#]*)#(.*)\1$
RewriteRule ^.*$ %2index.php [QSA,L]
Ответ 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.