golabs
golabs

Reputation: 331

.htaccess rewrite works but 503 redirect fails

Background

We, a group of whisky enthusiasts, only release a new whisky cask plan (product) once a week at Wednesdays at 1900 CET and since the demand to obtain a share in the casks exceeds the availability by many times, the server is more or less rampaged at 1900 CET and can thus do with all the server resources available.

Preferred Solution

After analyzing the logs of the last weeks I noticed that many of the > 800 members are also active simultaneously on the forum at the time of the release of the new cask plan (product). So to ease the load for the server a bit I want to make the forum temporarily unavailable between 1855 and 1915 CET, every Wednesday.

So I came up with the following code for the .htaccess to control this:

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/forum(/.*|$) [NC,OR]
RewriteCond %{REQUEST_URI} ^/timeline(/.*|$) [NC]
RewriteCond %{TIME_WDAY} =3
RewriteCond %{TIME_HOUR}%{TIME_MIN} >1654
RewriteCond %{TIME_HOUR}%{TIME_MIN} <1715
RewriteRule ^(.*)$ /503-Wednesday-1900CET.php [R=503,L]

Some notes:

I can test the above, without the 3 RewriteCond %{TIME_ lines, successfully on https://htaccess.madewithlove.be/

But when I try it on my server, with the 3 RewriteCond %{TIME_ lines disabled, it results in a 503 message from the server but it doesn't actually rewrites the url to the /503-Wednesday-1900CET.php file...

When I try it on my server, with the 3 RewriteCond %{TIME_ lines enabled, it results in a 500 message from the server and also doesn't actually rewrites the url to the /503-Wednesday-1900CET.php file...

My Questions

What might be the reason that the /503-Wednesday-1900CET.php file isn't served? I suspect the RewriteRule contains something the server doesn't accept but I don't see it.

And what might be the reason that the 3 RewriteCond %{TIME_ lines result in a 500 error message instead?

I already searched the web and Stackoverflow but I don't seem to find the trick to get me forward with this. So any hint is welcome at the moment.

Upvotes: 1

Views: 863

Answers (1)

MrWhite
MrWhite

Reputation: 45829

I can test the above, without the 3 RewriteCond %{TIME_ lines, successfully on https://htaccess.madewithlove.be/

The MWL tester tool is incorrect. When you specify a return status outside the 3xx range then the substitution string is ignored and the error document for the respective status code is served instead (or default server response if an ErrorDocument has not been explicitly defined). So, you need to define a custom ErrorDocument for the 503 status.

Not sure why you'd be getting a 500 error as there doesn't appear to be anything wrong with the directives you've posted, other than that mentioned above.

However, you do have to be careful that the error document itself does not trigger a 503 response - as this would result in an endless loop (500 error). You also have to be careful that any linked resources (images, CSS, etc.) are not also blocked. (Although you've not got so far as serving your error document yet).

Try the following instead:

RewriteEngine On

ErrorDocument 503 /503-Wednesday-1900CET.php

RewriteCond %{REQUEST_URI} ^/forum(/.*|$) [NC,OR]
RewriteCond %{REQUEST_URI} ^/timeline(/.*|$) [NC]
RewriteCond %{TIME_WDAY} =3
RewriteCond %{TIME_HOUR}%{TIME_MIN} >1654
RewriteCond %{TIME_HOUR}%{TIME_MIN} <1715
RewriteRule !^503 - [R=503]

Note that the substitution string in the RewriteRule directive is just a single hyphen (-) - indicating no substitution (it's ignored anyway).

The !^503 pattern is to ensure that the error document itself does not result in a 503 response (effectively an endless loop, that would result in the server's default error response with an additional message along the lines of "a 500 error was encountered trying to serve an ErrorDocument to handle the request".) Likewise, you will need to make sure that any linked resources are not also caught by this rule. It is generally preferable to have the 503 response as basic as possible.

You don't need the L flag when specifying a status code outside of the 3xx range.

I removed the RewriteBase / directive since it's not required here. However, if you have other directives that rely on this then obviously add it back.

Strictly speaking a 503 response should also come with a Retry-After HTTP response header containing the time the service is expected to return. (I assume you are setting this in your PHP script.)

Upvotes: 1

Related Questions