apache.htaccesshttp-redirectrewriting

.htaccess 301 redirect a directory, not working


I need to 301 redirect a directory and its included rewitten URLs:

/old-directory/any-url.html 301-redirected to /new-directory/any-url.html

and

/old-directory/ 301-redirected to /new-directory/

Inside that directory (moved to /new-directory), I have this directory-specific .htaccess with this rules I need to keep:

RewriteEngine On
RewriteRule ^list\.html$            list.php [QSA]
RewriteRule ^(.*)\.html$            index.php?hash=$1 [QSA,L]

Maybe it's not necessary to specify that, but on the root directory, I have this root .htaccess with rules that I don't want to interfere with:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^([a-zA-Z0-9-]*)$             index.php?page=$1 [QSA,L]

I tried to add this in the root .htaccess:

RewriteRule ^old-directory$         /new-directory/ [R=301,NC,L]
RewriteRule ^old-directory/(.*)$    /new-directory/$1 [R=301,NC,L]

...but it does not work (I get a 500 internal server error). Have you got an idea why? Since I successfully tested this rule on a .htaccess testing site, I guess it's because it interfere with the other /new-directory/ specific .htaccess... In that case, would it be better to merge the two .htaccess into one, and how?


Solution

  • This issue is, even when you fix your 500 error, your base rewrite rule will always take precedence because old-directory matches RewriteRule ^([a-zA-Z0-9-]*)$ so make sure the order is correct and you place your old-directory rules BEFORE the existing ones:

    RewriteEngine On
    
    RewriteRule ^old-directory(.*)$         /new-directory$1 [R=301,NC,L]
    
    RewriteCond %{REQUEST_FILENAME}.php -f
    RewriteRule ^([a-zA-Z0-9-]*)$             index.php?page=$1 [QSA,L]
    

    You'll notice I also simplified your rule. There's no reason you should have 2 lines for that.

    Don't forget that once redirected to new-directory, RewriteRule ^([a-zA-Z0-9-]*)$ (from the root dir) will still apply so you might need need to change it to:

    RewriteCond %{REQUEST_FILENAME}.php -f
    RewriteCond %{REQUEST_URI} !^new-directory
    RewriteRule ^([a-zA-Z0-9-]*)$             index.php?page=$1 [QSA,L]
    

    %{REQUEST_FILENAME}.php also looks a bit suspicious. You probably only need %{REQUEST_FILENAME}

    In the end, you need to sort the 500 error first by looking at the Apache error logs, and then reorganise your rules so they don't clash. You could potentially merge them. It's actually easier to merge them to control their order. Otherwise, they just cascade and it can become fairly complex.