apache.htaccesshttp-redirectmod-rewritemod-alias

Rewrite and Redirect not working together


I have the current .htaccess

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/+$ $1 [R=301,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([\w-]+)/([\w-]+)/?$ index.php?apar=$1&bpar=$2 [L,QSA]
RewriteRule ^([\w-]+)/?$ index.php?apar=$1 [L,QSA]

I would like to redirect some pages, which I would normally do, as per the following:

redirect 301 /old-page https://www.domain.co.uk/new-page

However, this seems to redirect to the page

https://www.domain.co.uk/new-page?apar=old&bpar=page

I can't get the old pages to redirect cleanly.


Solution

  • RewriteRule and Redirect belong to different Apache modules (mod_rewrite and mod_alias respectively). Consequently, they run independently and at different times during the request. mod_rewrite always runs before mod_alias, despite the apparent order of the directives in the config.

    For this reason you should avoid mixing directives from both modules to avoid unexpected conflicts like this. However, from your given example, I can't quite see where that resulting URL would come from, unless the request is for /old/page, rather than /old-page? (A request for /old-page would result in a redirect to /new-page?apar=old-page.)

    Since you are already using mod_rewrite, you should use mod_rewrite instead for this redirect and include it before your existing directives. For example:

    RewriteRule ^old-page$ https://www.example.com/new-page [R=301,L]
    

    Test first with 302 (temporary) redirects to avoid potential caching issues and you will need to clear your browser cache before testing, since this erroneous 301 (permanent) redirect will likely have been cached by the browser.


    Aside:

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^([\w-]+)/([\w-]+)/?$ index.php?apar=$1&bpar=$2 [L,QSA]
    RewriteRule ^([\w-]+)/?$ index.php?apar=$1 [L,QSA]
    

    You have a filesystem check (RewriteCond directive) before the first rule, but not before the second. (The filesystem check only applies to the first rule that follows.)

    In actual fact, that RewriteCond directive probably isn't required at all since the RewriteRule probably won't match real files anyway. Unless you have files without file extensions?!