2

I want to perform a maintenance on my website, so wrote an htaccess (I do not own the server) to redirect users to a specific page.

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !outoforder.html
RewriteRule .* "/outoforder.html" [R=503,L]
ErrorDocument 503 /outoforder.html
Header Set Cache-Control "max-age=0, no-store"
</IfModule>

It is working well. However, in some subfolders I have also some rewriting rules that seem to override this rule, therefore I am still able to access those subfolders. There are plenty of subfolders, so I do not want to modify all of them, to temporary disable the rewriting process, I would like to be able to do that in the root folder.

First I do not understand why those rules are still applied, I would have thought that due to RewriteRule .* "outoforder.html" [R=503,L] their files are not accessed then their writing rules should not be applied. Obviously, I am wrong.

Thus, how can I avoid the sub htaccess or disable from the root directory the ability to rewrite.

2 Answers 2

2

mod_rewrite is not inherited by default. So any mod_rewrite directives in a subdirectory/child .htaccess file will completely override the parent directives. Your mod_rewrite rule in the parent config that triggers the 503 is not even processed.

You can either enable mod_rewrite inheritance so that the directives from the current scope are processed before mod_rewrite directives in child configs. For example, in the parent config:

RewriteOptions InheritDownBefore

However, this could have many additional caveats. (InheritDownBefore also requires Apache 2.4.8+)

OR, use a mod_alias RedirectMatch directive to trigger the 503 instead and use a negative lookahead in the regex to prevent the error document itself from triggering the maintenance page.

For example:

RedirectMatch 503 ^/(?!outoforder\.html).*

Aside: If using mod_rewrite...

RewriteCond %{SCRIPT_FILENAME} !outoforder.html
RewriteRule .* "/outoforder.html" [R=503,L]

This should be implemented in a single directive, for example:

RewriteRule !outoforder\.html$ - [R=503]

The condition was superfluous - this check can be performed (more efficiently) in the RewriteRule directive itself. When using a return status outside of the 3xx range then the substitution string is ignored anyway, so it is preferable to use a single hyphen instead (ie. -) to explicitly indicate no-substitution. The L flag is also redundant in this case for the same reason - it is implied.

A slight caveat with the solution(s) above is that a request for the /outoforder.html URL/file itself will result in a 200 OK response by default, unless you are overriding this in the file itself (although this may not be possible if it is plain HTML and not using any server-side scripting, eg. PHP).

You can resolve this by using the following rule instead:

# Trigger a 503 for ALL user requests
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^ - [R=503]

This triggers a 503 for every direct request from the user, including requests for the 503 error document itself. The condition prevents the internal subrequest for the error document triggering another 503 response (infinite loop).

3
  • RewriteOptions InheritDownBefore did the job. Thank you! Commented Dec 20, 2021 at 13:03
  • 1
    You're welcome. However, enabling mod_rewrite inheritance can have additional caveats if you have other directives. Using mod_alias instead would be my preference.
    – MrWhite
    Commented Dec 20, 2021 at 13:05
  • RedirectMatch 503 ^/(?!outoforder\.html).* is also perfectly working. I take your advice ! Commented Dec 20, 2021 at 13:36
1

Rather than using the [L] flag, you need to use the [END] flag. From the documentation

Using the [END] flag terminates not only the current round of rewrite processing (like [L]) but also prevents any subsequent rewrite processing from occurring in per-directory (.htaccess) context.

The other issue that I see with your rules is that the destination path ("/outoforder.html") is never used on a RewriteRule with [R=503]. I would recommend using - for clarity there.

So your final rule set should be:

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !outoforder.html
RewriteRule .* - [R=503,END]
ErrorDocument 503 /outoforder.html
Header Set Cache-Control "max-age=0, no-store"
</IfModule>
2
  • The explanation of the END looked very promising, however it is still not working. I can access to all the subfolders... Commented Dec 20, 2021 at 13:00
  • 1
    Looks like mrwhite has a better answer for you. I'm glad his answer works. Commented Dec 20, 2021 at 13:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.