Using error_page to a named location - possible?
Maxim Dounin
mdounin at mdounin.ru
Tue Mar 6 23:28:55 UTC 2012
Hello!
On Tue, Mar 06, 2012 at 10:32:56PM +0000, Ed W wrote:
> On 06/03/2012 17:47, Maxim Dounin wrote:
> >>I can't see that it's possible to use something like:
> >>
> >> location / {
> >> proxy_pass http://127.0.0.1:3000;
> >> error_page 502 @502;
> >> }
> >>
> >>location @502 {
> >> index /502.html;
> >> root /var/www;
> >> internal;
> >>}
> >Try something like:
> >
> > location @502 {
> > internal;
> > root /var/www;
> > rewrite ^ /502.html break;
> > }
> >
> >This should work at least for GET requests.
>
> Perfect - thanks!
>
>
> Now, I have thought about this a little while and I don't quite
> understand how it works...?
>
> The key seems to be the rewrite clause - near as I can see, without
> this the error request gets reprocessed by the "location /" section,
> but the rewrite is causing it to terminate that?
>
> Can you teach me to understand this please?
Under normal conditions
location @502 {
root /var/www;
}
will behave much like normal static location, as described here:
http://nginx.org/en/docs/http/request_processing.html
That is, request to a "/file", if it happens to hit his location,
will be processed as follows:
1. It doesn't ends with '/', hence nginx will try to open a file
for it, <root> + <uri>. I.e. "/var/www/file" will be opened.
2. The (1) will likely fail (as there is no such file) and will
generate 404.
More importantly, request to a "/" will be processed as
follows:
1. It ends with "/", so nginx will try to use index module to
handle it.
2. Index module will test <root> + <uri> + <index> file, i.e.
"/var/www/502.html" with your config. If it's found - nginx will
do internal redirect to "/502.html".
3. The internal redirect will end up in "location /". This is
obviously not what you want.
With "rewrite ^ /502.html break;" the following two important
things happen:
a. Every request will be a request to a file (i.e. no internal
redirects). Note that "break" is important, without "break" nginx
will re-do location matching again after rewrite.
b. Every request will be a request to the "/var/www/502.html"
file.
That is, every GET request which hits the @502 location will
return the /var/www/502.html.
Note well:
For POSTs things won't be that easy, as error_page set to a named
location won't change request method to GET (in contrast to
error_page set to a uri), and the above will generate 405 Method
Not Allowed. If you have to handle POSTs as well, I see the
following options as of now:
1. Use proxy_pass to another server{} in location @502 and process
it there. You may also use proxy_method/proxy_pass_request_body
to simplify things.
2. Use some normally impossible location, like
location / {
proxy_pass http://backend;
error_page 502 //502.html;
}
location = //502.html {
root /var/www;
}
The (2) is more like a hack, but should work as //502.html isn't
normally reachable via nginx due to merge_slashes being "on" by
default (see http://nginx.org/r/merge_slashes).
Maxim Dounin
More information about the nginx
mailing list