Jeroen Versteeg
Jeroen Versteeg

Reputation: 353

RewriteRule in folder breaks parent (.htaccess)

# /.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:

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.

Upvotes: 1

Views: 337

Answers (3)

GiDo
GiDo

Reputation: 1340

With Apache 2.4, I've success by adding RewriteOptions InheritDownBefore in the parent .htaccess.

Upvotes: 0

MrWhite
MrWhite

Reputation: 45914

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.

Upvotes: 1

anubhava
anubhava

Reputation: 785631

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.

Upvotes: 1

Related Questions