skip to Main Content
# /.htaccess
RewriteEngine on
RewriteBase /
RewriteRule "^([^/]+)/root/(.*)"   "$1/index.php?root=$2"

# /folder/.htaccess
RewriteRule "^sub/(.*)"            "index.php?sub=$1"

Each folder’s RewriteRule works in isolation:

  • /folder/root/hi => /folder/index.php?root=hi
  • /folder/sub/hello => /folder/index.php?sub=hello

Q: Why does adding any RewriteRule in the subfolder (/folder/.htacces) break the one in the web root (causes 404)? What do I need to do to create rules on different levels?

I’ve tried adding RewriteOptions Inherit(Down), but that didn’t have any effect.

3

Answers


  1. Assuming you have RewriteEngine On in the /folder/.htaccess then the mod_rewrite directives in the parent config will be completely overridden, since mod_rewrite directives don’t inherit by default.

    However, even if you enable mod_rewrite inheritance, the directives still won’t work, because mod_rewrite inheritance “virtually copies” the directives “in-place”, as if the directives are in the same config file – in the same scope (with the same directory-prefix).

    So, with RewriteOptions Inherit in the /folder/.htaccess file, the directives are effectively processed like this:

    # /folder/.htaccess
    RewriteRule "^sub/(.*)"            "index.php?sub=$1"
    
    # Inherited from parent config
    RewriteRule "^([^/]+)/root/(.*)"   "$1/index.php?root=$2"
    

    The pattern "^([^/]+)/root/(.*)" simply won’t match if used in the scope of the /folder/.htaccess file – which is what’s happening when using mod_rewrite inheritance.

    IF the /.htaccess (root) directives are always inherited then you could modify the root directive to read something like the following (removing the parent directory from the rule):

    RewriteRule ^root/(.*) index.php?root=$1 [L]
    

    (Yes, it matches the directive already in the /folder/.htaccess file.)

    However, the “problem” now is that directive probably won’t work if not inherited as in your example. IF you specifically need it to work in both scenarios: when inherited from a subdirectory .htaccess file and directly from the document-root, then modify the directive to make the parent folder optional. For example:

    RewriteRule ^([^/]+/)?root/(.*) $1index.php?root=$3 [L]
    

    You may still need to fix the RewriteBase directive, or remove it altogether.

    mod_rewrite inheritance is not as useful as it at first appears. Directives – that are expected to be inherited – generally need to be specifically written to allow for this.

    Login or Signup to reply.
  2. You need to change your root .htaccess rule to this:

    RewriteRule ^([^/]+/)?root/(.*)$ $1index.php?root=$2 [L,QSA]
    

    This is to make initial part [^/]+/ an optional match in order to make same rule work from root .htaccess as well as from a /folder/.htaccess.

    Then have this in your folder/.htaccess:

    RewriteOptions Inherit
    RewriteEngine On
    
    RewriteRule ^sub/(.*)$ index.php?sub=$1 [L,QSA]
    

    RewriteOptions Inherit will inherit all rules and directives from parent .htaccess and will apply them in child’s context after applying all the rules defined in child .htaccess.

    Login or Signup to reply.
  3. With Apache 2.4, I’ve success by adding RewriteOptions InheritDownBefore in the parent .htaccess.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search