Search code examples
apache.htaccesshttp-redirectmod-rewritemod-alias

.htaccess 301 redirect with exclusion does not work


I try to use a simple 301 redirect from domain1.com/folder/ to domain2.com/

but excluding domain1.com/folder/subfolder

I use the following code in .htaccess:

RedirectMatch 301 ^/folder/((?!subfolder).*)$ https://domain2.com/$1

but it simply redirects all the requests, including the requests to subfolder.

Please, help to fix the line to make it work as described. Thank you!

here is the complete code of .htaccess

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /folder/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /folder/index.php [L]
</IfModule>
RedirectMatch 301 ^/folder/((?!subfolder).*)$ https://domain2.com/$1

Solution

  • Try it like this using mod_rewrite instead:

    (NB: This assumes the .htaccess file is located in the document root.)

    # /.htaccess
    
    # Redirect all direct requests, except "subfolder"
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteCond $1 !^subfolder($|/)
    RewriteRule ^folder/(.*) https://domain2.com/$1 [R=301,L]
    
    <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /folder/
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /folder/index.php [L]
    </IfModule>
    

    It is important that the redirect goes before the rewrite to your front-controller.

    You will need to ensure your browser cache is cleared before testing and test with a 302 (temporary) redirect to avoid potential caching issues.


    UPDATE:

    Yes, /folder has it's own .htaccess (this is the file I am working at all this time). Yes, /folder is where Wordpress is installed.

    In that case you would need to change the above redirect to read as follows (it won't do anything otherwise):

    # /folder/.htaccess
    
    # Redirect all direct requests, except "subfolder"
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteCond $1 !^subfolder($|/)
    RewriteRule (.*) https://domain2.com/$1 [R=301,L]
    

    Basically, you need to remove folder/ from the start of the regex that matches the URL-path. The URL-path that the RewriteRule pattern matches against is relative to the directory that contains the .htaccess file.

    The addition of the check against the REDIRECT_STATUS env var is to ensure that rewritten requests to the WP front-controller (when subfolder is requested) are not redirected.

    You can also "simplify" the WordPress directives that follow (although if these are enclosed in # BEGIN WordPress / # END WordPress comment markers then you should leave the directives as they are since they are maintained by WordPress). For example:

    RewriteEngine On
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . index.php [L]
    

    The RewriteBase directive is not required. And neither is the <IfModule> wrapper. (But as I said above, only change this if you are hand-coding the .htaccess and not letting WordPress maintain it.)