htaccess reverse directory

前端 未结 1 1074
我寻月下人不归
我寻月下人不归 2021-01-15 04:55

It is possible to let htaccess look for a specific file related to the url and go back one step if not found?

Example:

/example/here/where/from

相关标签:
1条回答
  • 2021-01-15 05:40

    This is very tricky but here is a code that recursively traverse to parent dir of the given REQUEST_URI and it supports infinite depth.

    Enable mod_rewrite and .htaccess through httpd.conf and then put this code in your .htaccess under DOCUMENT_ROOT directory:

    # Turn mod_rewrite on
    RewriteEngine On
    RewriteBase /
    
    # If the request is for a valid file
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    # If the request is for a valid link
    RewriteCond %{REQUEST_FILENAME} -l
    # don't do anything
    RewriteRule ^ - [L]
    
    # if current ${REQUEST_URI}.php is not a file then
    # forward to the parent directory of current REQUEST_URI
    RewriteCond %{DOCUMENT_ROOT}/$1/$2.php !-f
    RewriteRule ^(.*?)/([^/]+)/?$ $1/ [L]
    
    # if current ${REQUEST_URI}.php is a valid file then 
    # load it be removing optional trailing slash
    RewriteCond %{DOCUMENT_ROOT}/$1.php -f
    RewriteRule ^(.*?)/?$ $1.php [L]
    

    Explanation:

    Let's say original URI is: /index/foo/bar/baz. Also let's say that %{DOCUMENT_ROOT}/index.php exists but no other php files exist under DOCUMENT_ROOT.

    RewriteRule #1 has a regex that is breaking current REQUEST_URI into 2 parts:

    1. All but lowest subdir into $1 which will be index/foo/bar here
    2. Lowest subdir into $2 which will be baz here

    RewriteCond checks whether %{DOCUMENT_ROOT}/$1/$2.php (which translates to whether %{DOCUMENT_ROOT}/index/foo/bar/baz.php) is NOT a valid file.

    If condition succeeds then it is internally redirected to $1/ which is index/foo/bar/ here.

    RewriteRule #1's logic is repeated again to make REQUEST_URI as (after each recursion):

    1. index/foo/bar/
    2. index/foo/
    3. index/

    At this point RewriteCond fails for rule # 1 because ${DOCUMENT_ROOT}/index.php exists there.

    My RewriteRule #2 says forward to $1.php if %{DOCUMENT_ROOT}/$1.php is a valid file. Note that RewriteRule #2 has regex that matches everything but last slash and puts it into $1. This means checking whether %{DOCUMENT_ROOT}/index.php is a valid file (and it indeed is).

    At this point mod_rewrite processing is complete as no further rule can be fired since both RewriteCond fails after that, therefore %{DOCUMENT_ROOT}/index.php gets duly served by your Apache web server.

    0 讨论(0)
提交回复
热议问题