Is there any way to set RewriteBase to the path current folder (the folder which the .htaccess file is in) relative to the host root?
I have a CMS and if I move it to the directory in my host it does not work unless I set the RewriteBase to the path of directory relative to the root of host. I would like my CMS to work with only copy and paste, without changing any code in htaccess.
For example:
webroot
- sub_directory
- cms
- .htaccess
in this case I should write in the htaccess: RewriteBase /
and if I move the htaccess inside sub_directory I should change RewriteBase to:
RewriteBase /sub_directory/
So I want something like
RewriteBase /%{current_folder}/
Here is one way one can grab the RewriteBase
in an environment variable which you can then use in your other rewrite rules:
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]
Then you can use %{ENV:BASE}
in your rules to denote RewriteBase
, ie:
#redirect in-existent files/calls to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . %{ENV:BASE}/index.php [L]
This rule works by comparing the REQUEST_URI
to the URL path that RewriteRule
sees, which is the REQUEST_URI
with the leading RewriteBase
stripped away. The difference is the RewriteBase
and is put into %{ENV:BASE}
.
RewriteCond
, the LHS (test string) can use back-reference variables eg $1
, $2
OR %1
, %2
etc but RHS side ie condition string cannot use these $1
, $2
OR %1
, %2
variables.\\1
, \\2
etc.RewriteCond
first captured group is (.*?/)
. It will be represented by internal back-reference \\1
.RewriteBase
dynamically by comparing %{REQUEST_URI}
and $1
. An example of %{REQUEST_URI}
will be /directory/foobar.php
and example of $1
for same example URI will be foobar.php
. ^(.*?/)(.*)::\\2$
is putting the difference in 1st captured group %1
or \\1
. For our example it will populate %1
and \\1
with the value /directory/
which is used later in setting up env variable %{ENV:BASE}
in E=BASE:%1
.The accepted solution did not work for me, I think, but this did: https://web.archive.org/web/20180401034514/http://www.zeilenwechsel.de/it/articles/8/Using-mod_rewrite-in-.htaccess-files-without-knowing-the-RewriteBase.html
Long story short:
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond $0#%{REQUEST_URI} ([^#]*)#(.*)\1$
RewriteRule ^.*$ %2index.php [QSA,L]
Building on anubhava's answer and Jon Lin's , here's what I just came up with for myself (haven't used this in production nor tested this extensively yet).
Let's use this example URL, where .htaccess is in current_folder:
http://localhost/path_to/current_folder/misc/subdir/file.xyz
Filesystem: /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]
You can view the details of what's happening for yourself by using LogLevel alert rewrite:trace6
in your httpd.conf
in apache, and then looking in your error.log
.
Here's a bit more clarification on the following two lines, which I'd still found a bit confusing.
RewriteCond %{ENV:SUBPATH}::%{REQUEST_URI} ^(.*)::(.*?)\1$
RewriteRule ^ - [ENV=CWD:%2]
First off, the double colon ::
is not an operator of any sort; it's just an arbitrary delimiter. The RewriteCond
expands TestString %{ENV:SUBPATH}::%{REQUEST_URI}
to the following:
misc/subdir/file.xyz::/path_to/current_folder/misc/subdir/file.xyz
Then our CondPattern ^(.*)::(.*?)\\1$
:
^(.*)::
matches misc/subdir/file.xyz::
\\1
is the first capture group, misc/subdir/file.xyz
(.*?)\\1$
becomes (.*?)misc/subdir/file.xyz$
(.*?)
matches the remaining /path_to/current_folder/
And our RewriteRule
sets CWD
to %2
, which is the second capture group of CondPattern.
如果您在 htaccess 中有RewriteBase
命令,您可能会对此进行注释,然后它将自动解析到该目录。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.