To show maintenance page during deploy I've always used next config in nginx:
if (-f /home/shared/system/maintenance.html) {
return 503;
}
error_page 503 @maintenance;
location @maintenance {
root /home/shared/errors;
rewrite ^(.*)$ /maintenance.html break;
}
And everything was ok until I needed to add static content to maintenance page (images, stylesheets, etc.)
No of static content work with such logs in error.log:
2011/05/05 02:47:20 [notice] 13760#0: *6 "^(.*)$" matches "/some.jpg", client: x.x.x.x, server: server.com, request: "GET /some.jpg HTTP/1.1", host: "server.com"
2011/05/05 02:47:20 [notice] 13760#0: *6 rewritten data: "/maintenance.html", args: "", client: x.x.x.x, server: server.com, request: "GET /some.jpg 2 HTTP/1.1", host: "server.com"
Which is logical - if I do rewrite everything to maintenance.html that means that static content is not exclusion.
But I cannot find any proper solution to make redirect to every file except that ones which are physically existed in root /home/shared/errors
folder.
PS. /home/shared/errors
does not share any resources with common project folder - this is completely separate folder (even without any symlinks to /current
for the project.
I'm sorry, Frank Farmer, but this doesn't work.
What works but not so neat:
And how requests work ->
I use rule #1
if (-f /home/shared/system/maintenance.html) {
return 503;
}
this rule has a support of named location location @maintenance
and for the common redirect to /maintenance.html
at root /home/shared/errors
everything works.
this page contains and image some.jpg
- to receive this image browser starts new request and this new request again hits rule #1
all of this was described in initial question BUT
if I use some if
magic like in Frank Farmer's answers I can point server to requested file BUT HTTP answer will be 503 and browsers (all, except Safari, in my test) throws errors in debug console and do show image but do not process CSS-files in the same situation.
And this is critical.
I tried to resolve this using location magic for my new content-requests - that means that I have to:
do NOT return 503
for content requests and skip named location at all.
do change root /home/shared/errors
because maintenance content is still there.
Finally, I've got next solution:
create maintenance-static
folder for all static content and change paths in my maintenance.html
file and maintenance-static stylesheets
next use these rules (I believe they are self-descriptive) which replace single if (-f /home/shared/system/maintenance.html)
in initial question:
set $can503 0;
if (-f /home/shared/system/maintenance.html) {
set $can503 1;
}
if ($uri ~* /maintenance-static/) {
set $can503 0;
}
location /maintenance-static/ {
root /home/shared/errors;
}
if ($can503 = 1) {
return 503;
}
This solution works without any errors in all browsers and for numerous of pages in shared/errors
folder, for ex. maintenance.html, error.html, overload.html, etc.
This solution is not really clear - probably you can hint me how I can make it neater, but remembering we are dealing with separate requests (and separate nginx processes for each file/request in case of high load, etc.) for initial html and its content we cannot use same rule with 503 redirecting for all files.
I spent a good two hours looking for an answer to this problem, and finally found this post. Seems like it should be more common. My solution fell somewhere in between Frank's and Wile's. As stated by Wile, certain browsers (Chrome for instance) will choose to not render the CSS/JS of any files that came back 503, even if it fully and properly fetched them.
But there's a fix that's less hacky than what Wile did. Simply return 200!
My full solution was as follows:
error_page 503 @maintenance;
location @maintenance {
root /path_to_static_root;
if (!-f $request_filename) {
rewrite ^(.*)$ /rest_of_path/maintenance.html break;
}
return 200;
}
Worked like a charm. :)
location @maintenance {
root /home/shared/errors;
rewrite (some\.jpg|some2\.gif)$ /$1 break;
rewrite ^(.*)$ /maintenance.html break;
}
This might work without enumerating the whitelisted files:
location @maintenance {
root /home/shared/errors;
if (!-f $request_filename) {
rewrite ^(.*)$ /maintenance.html break;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With