Search code examples
.htaccessmod-rewriteapacheapache-config

How can I redirect all sub-directories to root using htaccess or httpd.conf?


I have an index file that builds content based on n PATH_INFO variables.

Example:

site.com/A/B/n/

should use index.php at either:

site.com/index.php?var1=A&var2=B&varN=n
 - or - 
site.com/index.php/A/B/n/

instead of:

site.com/A/B/n/index.php || which doesn't exist ||

So far I've tried a number of variations of:

RedirectMatch ^/.+/.*$ /

with no success.

I have an inelegant and unscalable solution here:

RewriteEngine On 
RewriteRule ^([a-zA-Z0-9_-]+)/?$ index.php?p1=$1 [NC,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?p1=$1&p2=$2 [NC,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?p1=$1&p2=$2&p3=$3 [NC,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?p1=$1&p2=$2&p3=$3&p4=$4 [NC,L]

Problems with this solution:

  • Inelegant and unscalable, requires manual line for each subdirectory
  • Fails with non alphanumeric characters (primarily +,= and &) ex. site.com/ab&c/de+f/ (note, even changing the regex to ^([a-zA-Z0-9_-\+\=\&]+)/?$ does little to help and actually makes it error out entirely)

Can you help?


Solution

  • Option 1: (site.com/index.php?var1=A&var2=B&varN=n):

    Options +FollowSymLinks -MultiViews
    RewriteEngine On
    
    # do not do anything for already existing files
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule .+ - [L]
    
    RewriteRule ^([^/]+)/?$ index.php?p1=$1 [QSA,L]
    RewriteRule ^([^/]+)/([^/]+)/?$ index.php?p1=$1&p2=$2 [QSA,L]
    RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ index.php?p1=$1&p2=$2&p3=$3 [QSA,L]
    RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ index.php?p1=$1&p2=$2&p3=$3&p4=$4 [QSA,L]
    

    1. You had [NC] flag ... so there were no need to have A-Z in your pattern.

    2. Instead of [a-zA-Z0-9_-\+\=\&] or [a-zA-Z0-9_-] I use [^/] which means any character except slash /.

    3. [QSA] flag was added to preserve existing query string.

    Option 2: (site.com/index.php/A/B/n/):

    Options +FollowSymLinks -MultiViews
    RewriteEngine On
    
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule (.*) index.php/$1 [L]
    

    In reality, if you do not plan to show that URL anywhere (like, 301 redirect etc), the last line can easily be replaced by RewriteRule .* index.php [L] -- you will look for original URL using $_SERVER['REQUEST_URI'] in your PHP code anyway.