Welcome to WebmasterWorld Guest from 54.145.44.134

Forum Moderators: Ocean10000 & incrediBILL & phranque

Message Too Old, No Replies

exclude root from maintenance redirect

Stop htaccess from redirecting root / or empty uri requests

     

nisiwi

1:44 am on Jan 28, 2013 (gmt 0)

5+ Year Member



Hello all,

Wondered if you could help with this one.

The following htaccess rules force all requests to a maintenance page except when accessed from a specific IP (address removed).

I'm using this with Wordpress.

This seems to works fine for all front end pages, however for some reason all requests for wp-admin and root or domain without a URI are still getting redirected which means that the IP address excluded is unable to see the root or home page and instead receives the maintenance page.

RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^xx\.xxx\.xxx\.xxx$
RewriteCond %{REQUEST_URI} !^maintenance$ [NC]
RewriteCond %{REQUEST_URI} !^\.(jpe?g?|png|gif)$ [NC]
RewriteRule ^(.*)$ maintenance [R=302,L]

Can anyone advise how I stop the root / requests without a URI / home page from being redirected ?

Have spent quite a few hours on this and I just can't see it. Hope someone can set me on the right track.

Thanks,

Nic

g1smd

2:16 am on Jan 28, 2013 (gmt 0)

WebmasterWorld Senior Member g1smd is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



You should return "503 Unavailable" during maintenance.

The 302 redirect is a disaster.

You should rewrite (that's internally rewrite, not externally redirect) those requests to a PHP script that delivers a 503 HEADER and the human readable error message.

.* is all pages including root. The ( and ) are unecessary when you're not re-using the capture. The ^ and $ are unecessary because .* matches the entire input.

RegEx pattern for NOT root is . or .+ or !^$ - pick one.

lucy24

4:18 am on Jan 28, 2013 (gmt 0)

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time Top Contributors Of The Month



You should rewrite (that's internally rewrite, not externally redirect) those requests to a PHP script that delivers a 503 HEADER and the human readable error message.

Can't you do it upfront in htaccess combined with your custom 503 page? Fine print (under #flag_r) [httpd.apache.org] says that you can attach any number to the R= flag, not just a redirect.

Tangential question:
RewriteCond %{REQUEST_URI} !^\.(jpe?g?|png|gif)$ [NC] 

What's the reason for this exemption? Just to let search engines continue to pick up images, since they're unaffected by the reconstruction going on elsewhere?

Either way, seems like you'd do better to make it part of the Rule itself:

RewriteRule ^([^/.]+/)*([^/.]+\.html)?$ {et cetera}


Don't cut and paste: exact wording is off the top of my head. You may want to include css in the rule, since it's probably changing a bit too. So (?:css|html) or similar. If you've got a seriously overloaded server, all parentheses everywhere can be expressed as (?:blahblah) to make them non-capturing.

nisiwi

8:20 am on Jan 28, 2013 (gmt 0)

5+ Year Member



Hi lucy24,

That's what I was hoping for. I've got a custom 503 page and I was looking to trigger the redirect under certain conditions as I want some parts of the site live and others redirecting.

OK, so I've modified the rewriterule [R=503,L]

No real reason for this actually: RewriteCond %{REQUEST_URI} !^\.(jpe?g?|png|gif)$ [NC]
I was playing around with conditions so its been removed.

=========================

Hi g1smd

I'd tried using . or .+ or !^$ and tested for this conditionally. Are you saying I should bee using it in the rewriterule ?

So I've now got

RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^xx\.xxx\.xxx\.xxx$
RewriteCond %{REQUEST_URI} !^maintenance$ [NC]
RewriteRule !^$ maintenance [R=503,L]

nisiwi

9:10 am on Jan 28, 2013 (gmt 0)

5+ Year Member



When using this...

RewriteCond %{REMOTE_ADDR} !^xx\.xxx\.xxx\.xxx$
RewriteCond %{REQUEST_URI} !^maintenance$ [NC]
RewriteRule .+ maintenance [R=503,L]

or if I use !^$ OR . in the RewriteRule and access site through a proxy (different IP) I'm still getting the page requested and not the maintenance page ?

g1smd

9:21 am on Jan 28, 2013 (gmt 0)

WebmasterWorld Senior Member g1smd is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



You'll need to add another condition to check the REMOTE_ADDR is not that of the proxy.

nisiwi

9:58 am on Jan 28, 2013 (gmt 0)

5+ Year Member



I got this working with the following;

RewriteCond %{REQUEST_URI} !maintenance [NC]
RewriteCond %{REMOTE_ADDR} !xx\.xxx\.xxx\.xxx$
RewriteRule .? maintenance [R=503,L]

As my %{REMOTE_ADDR} condition is checking for NOT ! it only passes through if it does not match the IP.

Not sure why I would need to check for a proxy g1smd ? The point of the proxy (in this instance) was to mask the IP whilst I was checking that everybody else would be redirected apart from those accessing from the specific IP address. The proxy was for simulating a visitor from another IP.

g1smd

10:07 am on Jan 28, 2013 (gmt 0)

WebmasterWorld Senior Member g1smd is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



I misunderstood why you were accessing via proxy.

.? and .* match all pages including root.

. and .+ and !^$ match all pages not including root.

nisiwi

10:23 am on Jan 28, 2013 (gmt 0)

5+ Year Member



For some reason when I accessed the site from the IP that was allowed to pass it was still redirecteding the root and wp-admin.

Now that I've changed the rewrite cond/rule to:

RewriteCond %{REQUEST_URI} !maintenance [NC]
RewriteCond %{REMOTE_ADDR} !xx\.xxx\.xxx\.xxx$
RewriteRule .? maintenance [R=503,L]

I don't have any problems g1smd ?

lucy24

10:28 am on Jan 28, 2013 (gmt 0)

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time Top Contributors Of The Month



RewriteRule .? maintenance [R=503,L]


Note that the "R=503" element is just mod_rewrite's wonky wording; you're not really redirecting. The target-- if any-- is ignored, the server hands out a 503 and humans get your custom 503 page. So you also need an ErrorDocument line pointing to the "maintenance" page.

If you don't want requests for the front page to get the 503, you may need to do the opposite of a normal index-redirect and say something like
{THE_REQUEST} /
(with surrounding syntax, of course). This is in case the request passed through mod_dir before it got to mod_rewrite. If this happens there would never be a request for / alone but always "index.html". I have been bitten by this one myself.

Oh, and you shouldn't need the [NC]. Since it's an internal request, there's no chance of it being mis-capitalized. Supposed someone explicitly asks for MaintenAncE and is allowed through? They'll end up getting your 404 page instead.

nisiwi

10:56 am on Jan 28, 2013 (gmt 0)

5+ Year Member



What I'm trying to achieve is to be able to redirect any part of the site to a maintenance page (or vice versa) as each part is either being rebuilt or has been rebuilt.

Right now I want all pages for visitors (not equal to %{REMOTE_ADDR}) to be sent to a maintenance page and all pages requested from the %{REMOTE_ADDR} to be passed through.

When I use the following rules;

RewriteCond %{REQUEST_URI} !maintenance
RewriteCond %{REMOTE_ADDR} !xx\.xxx\.xxx\.xxx$
RewriteRule .? maintenance [R=503,L]

It works almost exactly as I need it, however if I now make a request for the maintenance page to view it from the %{REMOTE_ADDR} I would expect to be served that page, however I get redirect back to the front page ?

I think what you're saying lucy24 is that I need to test for THE_REQUEST ?

Would this work ?

RewriteCond %{THE_REQUEST} !/
RewriteCond %{REQUEST_URI} !maintenance
RewriteCond %{REMOTE_ADDR} !xx\.xxx\.xxx\.xxx$
RewriteRule !^$ maintenance [R=503,L]

I'm using a wordpress page "maintenance" as the custom 503 page.

nisiwi

12:08 pm on Jan 28, 2013 (gmt 0)

5+ Year Member



As I'm using a wordpress page for my 503 I've modified the rewriterule;

RewriteRule .? maintenance [R=302,L] - which is a moved temporarily

On being redirected to the maintenance page the 503 header (Service Temporarily Unavailable) will then be output.

I now have control over the conditions that trigger the maintenance page.

RewriteCond %{REQUEST_URI} !maintenance [NC]
RewriteCond %{REMOTE_ADDR} !xx\.xxx\.xxx\.xxx$
RewriteRule .? maintenance [R=302,L]

Requests for the maintenace page from %{REQUEST_URI} are also being served OK.

nisiwi

4:30 pm on Jan 28, 2013 (gmt 0)

5+ Year Member



Nope, looks like some strange goings on....I'm going to have to wait for DNS changes to settle down as I'm getting inconsistent results.

nisiwi

9:35 am on Jan 29, 2013 (gmt 0)

5+ Year Member



Finally a stable and working outcome.

As my 503 error page is actually a wordpress page (themed) I've gone with the following that seems to be working.

RewriteCond %{REQUEST_FILENAME} !\.(gif|jpe?g|png|css|js)$ - design files not blocked ?
RewriteCond %{REQUEST_URI} !^maintenance?$ - exclude maintenance page itself
RewriteCond %{REMOTE_ADDR} !=xx.xxx.xxx.xxx - allow specific IP
RewriteCond %{HTTP:X-FORWARDED-FOR} !=xx.xxx.xxx.xxx- allow specific IP (load balanced)
RewriteRule ^(.*)$ maintenance/ [R=302,NC,L] - otherwise redirect

The error is sent on the wp themed page by ensuring that <?php die(); ?> is output after error content is displayed.

Not sure if I actually need the first line as the user is not requesting those files ?

g1smd

10:36 am on Jan 29, 2013 (gmt 0)

WebmasterWorld Senior Member g1smd is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



Returning 302 is the wrong response. You should not be redirecting requests to a different URL.

You should be returning the 503 at the originally requested URL.

nisiwi

12:04 pm on Jan 29, 2013 (gmt 0)

5+ Year Member



Yes g1smd I understand. I've updated the rules and added the errodoc to htaccess.

RewriteRule ^(.*)$ maintenance/ [R=503,NC,L]

lucy24

12:22 am on Jan 30, 2013 (gmt 0)

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time Top Contributors Of The Month



Just to double-check that we're all on the same page haha

RewriteRule ^(.*)$ maintenance/ [R=503,NC,L] 


In this Rule, the "maintenance/" element is purely for your own information. It is ignored by mod_rewrite because the number after "R=" is outside the 3xx range.

Oh and, ahem, the [NC] is utterly unnecessary since you're not looking for some specific text. The [L] is technically superfluous since anything outside of R=3xx carries an automatic [L], but will do no harm.

g1smd

12:45 am on Jan 30, 2013 (gmt 0)

WebmasterWorld Senior Member g1smd is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



After the various Conditions I use this rule:

RewriteRule .* /temp503.php [L]


where the first line of temp503.php uses the PHP HEADER directive to send the 503 response back to the browser and inform the "retry-after" value.

The remainder of the PHP script generates the human readable HTML page containing the details of why the site is offline.

The .* pattern matches all requested pages of the site, including root; replace .* with something more specific if necessary.

nisiwi

8:32 am on Jan 30, 2013 (gmt 0)

5+ Year Member



Yes lucy24, thankyou for ensuring I tidy this up correctly.

So I would either;

ErrorDocument 503 /maintenance/
RewriteRule ^(.*)$ [R=503] - errordoc takes care of the page to be served

- should I still send the 503 header via the maintenance page itself (which I'm doing with PHP) ?

OR

RewriteRule ^(.*)$ maintenance/ [L] - to send to the maintenance page and send the 503 with PHP

Using whatever pattern matches and rewrites to suit.

nisiwi

9:14 am on Jan 30, 2013 (gmt 0)

5+ Year Member



Hmmm, the only way I get the correct result (503 header when requesting any page and the maintenance page served) is by using;

RewriteRule ^(.*)$ maintenance/ [R=503,L]

If I use (below) I get a 200 OK ?

RewriteRule ^(.*)$ [R=503]

g1smd

9:41 am on Jan 30, 2013 (gmt 0)

WebmasterWorld Senior Member g1smd is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



The last rule is missing a target, in this case a hyphen is used as placeholder, and the [L] flag.

See also msg:4540381.

nisiwi

10:12 am on Jan 30, 2013 (gmt 0)

5+ Year Member



So, more like this for the last rule.

RewriteRule ^(.*)$ - [R=503] as lucy24 said the [L] is technically superfluous since anything outside of R=3xx carries an automatic [L] ?

I tested and it works fine.

g1smd

10:16 am on Jan 30, 2013 (gmt 0)

WebmasterWorld Senior Member g1smd is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month



Since you're not re-using $1 there's no need to "capture" it. And since .* is greedy and matches "everything", there's no need for ^ or $ here.

^(.*)$ simplifies to .*

Yes, the [L] flag is not needed if the code is 4xx or 5xx, rather than 3xx. I forgot about that.

nisiwi

10:44 am on Jan 30, 2013 (gmt 0)

5+ Year Member



Ah, yes g1smd that slims if further, thank you and lucy24
 

Featured Threads

Hot Threads This Week

Hot Threads This Month