Set RewriteBase to the current folder path dynamically

Eeliya picture Eeliya · Jan 11, 2014 · Viewed 13k times · Source

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.

Update:

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}/

Answer

anubhava picture anubhava · Jan 11, 2014

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, i.e.:

#redirect in-existent files/calls to index.php
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule . %{ENV:BASE}/index.php [L]

Explanation:

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}.

  • In a RewriteCond, the LHS (test string) can use back-reference variables e.g. $1, $2 OR %1, %2 etc but RHS side i.e. condition string cannot use these $1, $2 OR %1, %2 variables.
  • Inside the RHS condition part only back-reference we can use are internal back-references i.e. the groups we have captured in this condition itself. They are denoted by \1, \2 etc.
  • In the RewriteCond first captured group is (.*?/). It will be represented by internal back-reference \1.
  • As you can make out that this rule is basically finding 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.