Home > front end >  Putting RewriteEngine On in subdir .htaccess file disables rewrites regarding this subdir specified
Putting RewriteEngine On in subdir .htaccess file disables rewrites regarding this subdir specified

Time:06-29

I have working rewrite rule in /.htaccess file:

RewriteCond %{REQUEST_URI} ^/wp-content/uploads/sites/[0-9] /xxx_uploads/ [NC]
RewriteRule wp-content/uploads/sites/[0-9] /xxx_uploads/(.*) wp-content/files.php?file=xxx_uploads/$1 [R=302,L]

which disallows unauthorized users viewing files in specific directories.

It works as long as there is nothing in /wp-content/uploads/.htaccess

If I put at least RewriteEngine On there, the rule from root .htaccess stops working.

It seems there is nothing with inheritance as RewriteOptions Inherit doesn't change anything. The question is: how to make the rule from root .htaccess work with rules in subdirectory .htaccess?

Apache 2.4.38

CodePudding user response:

What you describe is expected behaviour. mod_rewrite directives are not inherited by default. So if you enable (or disable) the rewrite engine in a child config it completely overrides mod_rewrite directives in the parent config.

It seems there is nothing with inheritance as RewriteOptions Inherit doesn't change anything.

It should, however...

RewriteOptions Inherit would need to go in the /wp-content/uploads/.htaccess file, not in the root /.htaccess file. However, mod_rewrite "inheritance" works by virtually copying the directives in-place. So this will not help in this instance since the RewriteRule directive as posted will not match when "inherited", ie. when virtually copied to the /wp-content/uploads/.htaccess file.

To resolve this, you can enable mod_rewrite inheritance in the parent (root) .htaccess file using RewriteOptions InheritDownBefore (requires Apache 2.4.8) and modify the rule so that it would work in both the root and child .htaccess files (in fact, anywhere).

For example:

# /.htaccess

RewriteEngine On
RewriteOptions InheritDownBefore

RewriteCond %{REQUEST_URI} ^/wp-content/uploads/sites/[0-9] /xxx_uploads/(.*) [NC]
RewriteRule . /wp-content/files.php?file=xxx_uploads/%1 [R=302,L]

This rule will now work regardless of where the .htaccess file is located (or where it is inherited). Note that %1 (as opposed to $1) is a backreference to the preceding CondPattern instead.

Note the slash prefix on the substitution string to make it a root-relative URL-path.

However, this may not work if you have other directives in the root .htaccess file, as these will also be "inherited".


Alternatively, you put your rule(s) in a server or virtualhost context (not inside a <Directory> container) and they will always run before the directives in any child .htaccess files.


Aside:

RewriteCond %{REQUEST_URI} ^/wp-content/uploads/sites/[0-9] /xxx_uploads/ [NC]
RewriteRule wp-content/uploads/sites/[0-9] /xxx_uploads/(.*) wp-content/files.php?file=xxx_uploads/$1 [R=302,L]

As written, the RewriteCond directive is entirely superfluous. (Providing the RewriteRule pattern is anchored, ie. ^wp-content/....)

  • Related