.htaccessmod-rewritemod-alias

.htaccess redirect all subfolders to specific path


I have multiple sites (subdirectories). I want to redirect all URLs of the format /(*)/login to /other/login.

I have tried:

RewriteRule ^/(.*)/login /other/login
#and 
^(.*)/login /other/login

I've also tried Redirect.

Additionally, I notice that some subfolders have their own .htaccess files also. Do I need to put the redirect rule in the subfolder's .htaccess file? There surely must be a more efficient way.


Solution

  • I notice some subfolder have their own .htaccess files also, do I need to put the redirect rule in the subfolder .htaccess files?

    Any mod_rewrite directives in child .htaccess files will, by default, completely override the mod_rewrite directives in any parent .htaccess file, they are not inherited. However, you can change this behaviour. On Apache 2.2 this is quite limited as you would need to change the child .htaccess file anyway, so it would probably be easier to simply duplicate this directive in the child config. But on Apache 2.4.8+ you can do all this in the parent .htaccess file. For example:

    RewriteEngine On
    RewriteOptions InheritDownBefore
    
    RewriteCond %{REQUEST_URI} !^/other
    RewriteRule ^[^/]+/login$ /other/login [R=302,L]
    

    The InheritDownBefore option results in the current mod_rewrite directives being applied before the mod_rewrite directives in any child configs.

    The RewriteCond directive is required in order to prevent a redirect loop (if the /other subdirectory does not have its own .htaccess file containing mod_rewrite directives).

    This is an external "redirect" (as stated in your question). The URL changes in the browser's address bar. You can possibly change this to an internal rewrite (as your current directive implies) by removing the R flag (although this may depend on your application).


    If you simply want a "redirect" then you could probably use a mod_alias RedirectMatch directive instead of the above mod_rewrite directives. This runs separately to mod_rewrite, but note that any mod_rewrite directives (in child configs) are processed first. For example:

    RedirectMatch 302 ^/(?!other)[^/]+/login$ /other/login
    

    The RedirectMatch directive uses a regex, whereas Redirect (also mod_alias) uses simple prefix matching. So, you couldn't match this specific pattern using a simply Redirect.

    The (?!other) part is a negative lookahead (zero-width assertion) that checks that the URL-path being matched does not start other - in order to avoid a redirect loop.

    Note also that RewriteRule does not use the slash prefix on the URL-path, whereas, RedirectMatch does. And there is no need to capture the URL-path (ie. by enclosing the regex in parentheses) if this is not required.