Set RewriteBase to the current folder path dynamically

后端 未结 3 1770
-上瘾入骨i
-上瘾入骨i 2020-11-28 03:45

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 t

3条回答
  •  半阙折子戏
    2020-11-28 04:38

    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$:

    1. ^(.*):: matches misc/subdir/file.xyz::
    2. \1 is the first capture group, misc/subdir/file.xyz
    3. (.*?)\1$ becomes (.*?)misc/subdir/file.xyz$
    4. Thus, our second capture group (.*?) matches the remaining /path_to/current_folder/

    And our RewriteRule sets CWD to %2, which is the second capture group of CondPattern.

提交回复
热议问题