# Using error\_page to a named location - possible?

**URL:** <https://www.ruby-forum.com/t/using-error-page-to-a-named-location-possible/217612>\
**Category:** NGINX\
**Created:** [March 6, 2012, 5:38pm UTC](https://www.ruby-forum.com/t/using-error-page-to-a-named-location-possible/217612 "2012-03-06T17:38:40Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![dubstep](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/cdc98d/32.png) [@dubstep](https://www.ruby-forum.com/u/dubstep)\
**Post date:** [March 6, 2012, 5:38pm UTC](https://www.ruby-forum.com/t/using-error-page-to-a-named-location-possible/217612/1 "2012-03-06T17:38:40Z")

</div>

Hi, as part of a larger problem I have a captive portal which grabs all  
incoming URLs and after evaluating a bunch of logic redirects the caller  
somewhere else. I use proxy\_pass to pass the request to my cgi code.

However, I would like to customise the error message in the event that  
the upstream daemon is unavailable. I can’t figure out how to do that  
affecting part of the incoming URLs. Is it possible to do something  
like “error\_page @502\_error” in conjunction with proxy\_pass?

So, I have

server {  
listen 8000 default\_server;

root /var/www/cp/htdocs/public;

location / {  
proxy\_read\_timeout 5;  
proxy\_pass [http://127.0.0.1:3000](http://127.0.0.1:3000);  
error\_page 502 /502.html;  
proxy\_set\_header Host $http\_host;  
proxy\_set\_header X-Server-Addr $server\_addr;  
proxy\_set\_header X-Forwarded-For $proxy\_add\_x\_forwarded\_for;  
proxy\_set\_header X-Forwarded-HTTPS 0;  
proxy\_set\_header X-Captive-Portal-Redirect 1;  
}  
location /502.html {  
internal;  
}  
}

However, if I visit “[http://somewhere/502.html](http://somewhere/502.html)” I get a 404 response  
(presumably matching the location /502.html and the 404 is due to the  
“internal”?)

I can’t see that it’s possible to use something like:

location / {  
proxy\_pass [http://127.0.0.1:3000](http://127.0.0.1:3000);  
error\_page 502 @502;  
}

location @502 {  
index /502.html;  
root /var/www;  
internal;  
}

Does someone have a suggestion on how to customise the error response  
without affecting ANY incoming URLs (they must ALL be passed through the  
proxy under normal working situation)

(Its occured to me that I could perhaps setup another “server { }” block  
listening on another port, then use a different proxy\_pass in the  
“location @502 {}”? Seems ugly, but would that work?)

Thanks for any thoughts

Ed W

---

<div class="post-metadata">

**Author:** ![ewildgoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@ewildgoose](https://www.ruby-forum.com/u/ewildgoose)\
**Post date:** [March 6, 2012, 5:41pm UTC](https://www.ruby-forum.com/t/using-error-page-to-a-named-location-possible/217612/2 "2012-03-06T17:41:47Z")

</div>

2012/3/6 Ed W [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Does someone have a suggestion on how to customise the error response  
> without affecting ANY incoming URLs (they must ALL be passed through the  
> proxy under normal working situation)

Try location = /502.html { } instead.

---

<div class="post-metadata">

**Author:** ![ewildgoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@ewildgoose](https://www.ruby-forum.com/u/ewildgoose)\
**Post date:** [March 6, 2012, 6:48pm UTC](https://www.ruby-forum.com/t/using-error-page-to-a-named-location-possible/217612/3 "2012-03-06T18:48:17Z")

</div>

Hello!

On Tue, Mar 06, 2012 at 04:37:41PM +0000, Ed W wrote:

> Hi, as part of a larger problem I have a captive portal which grabs  
> all incoming URLs and after evaluating a bunch of logic redirects  
> the caller somewhere else. I use proxy\_pass to pass the request to  
> my cgi code.
> 
> However, I would like to customise the error message in the event  
> that the upstream daemon is unavailable. I can’t figure out how to  
> do that affecting part of the incoming URLs. Is it possible to do  
> something like “error\_page @502\_error” in conjunction with  
> proxy\_pass?

Yes, see below.

> ```
> proxy_pass http://127.0.0.1:3000;
> 
> ```
> 
> }
> 
> However, if I visit “[http://somewhere/502.html](http://somewhere/502.html)” I get a 404 response  
> (presumably matching the location /502.html and the 404 is due to  
> the “internal”?)

Yes.

> internal;  
> }

Try something like:

```
location @502 {
    internal;
    root /var/www;
    rewrite ^ /502.html break;
}

```

This should work at least for GET requests.

> Does someone have a suggestion on how to customise the error  
> response without affecting ANY incoming URLs (they must ALL be  
> passed through the proxy under normal working situation)
> 
> (Its occured to me that I could perhaps setup another “server { }”  
> block listening on another port, then use a different proxy\_pass in  
> the “location @502 {}”? Seems ugly, but would that work?)

This should work too.

Maxim D.

---

<div class="post-metadata">

**Author:** ![ewildgoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@ewildgoose](https://www.ruby-forum.com/u/ewildgoose)\
**Post date:** [March 6, 2012, 7:24pm UTC](https://www.ruby-forum.com/t/using-error-page-to-a-named-location-possible/217612/4 "2012-03-06T19:24:25Z")

</div>

Hello!

On Tue, Mar 06, 2012 at 10:05:03PM +0400, Max wrote:

> > > ```
> > > proxy_set_header X-Server-Addr $server_addr;
> > > 
> > > ```
> > > 
> > > However, if I visit “[http://somewhere/502.html](http://somewhere/502.html)” I get a 404 response  
> > > }
> 
> ```
> # all named locations are internal by default, hence no "internal;"
> return 502 "Gateway error while servicing $request_uri!\n";
> 
> ```
> 
> }

The proxy\_intercept\_errors isn’t needed to handle 502’s generated  
by nginx, it’s only needed when backend returns the error in  
question and one want to override it.

Maxim D.

---

<div class="post-metadata">

**Author:** ![ewildgoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@ewildgoose](https://www.ruby-forum.com/u/ewildgoose)\
**Post date:** [March 6, 2012, 7:39pm UTC](https://www.ruby-forum.com/t/using-error-page-to-a-named-location-possible/217612/5 "2012-03-06T19:39:57Z")

</div>

06 марта 2012, 22:24 от Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> > > > Hi, as part of a larger problem I have a captive portal which grabs  
> > > > Yes, see below.  
> > > > proxy\_read\_timeout 5;  
> > > > }
> > 
> > ```
> > error_page 502 @502;
> > 
> > ```
> > 
> > }
> > 
> > location @502 {  
> > # all named locations are internal by default, hence no “internal;”  
> > return 502 “Gateway error while servicing $request\_uri!\n”;  
> > }
> 
> The proxy\_intercept\_errors isn’t needed to handle 502’s generated  
> by nginx, it’s only needed when backend returns the error in  
> question and one want to override it.

Perhaps I misunderstood the OP, but he mentioned passing the  
request to his cgi code, but mentioned no fastcgi\_pass directives,  
so it seems he wants to intercept 502 errors from the backend  
server.

Max

---

<div class="post-metadata">

**Author:** ![ewildgoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@ewildgoose](https://www.ruby-forum.com/u/ewildgoose)\
**Post date:** [March 6, 2012, 7:05pm UTC](https://www.ruby-forum.com/t/using-error-page-to-a-named-location-possible/217612/6 "2012-03-06T19:05:42Z")

</div>

06 марта 2012, 21:47 от Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> > that the upstream daemon is unavailable. I can’t figure out how to  
> > listen 8000 default\_server;  
> > proxy\_set\_header X-Forwarded-HTTPS 0;  
> > the “internal”?)
> 
> Yes.
> 
> > I can’t see that it’s possible to use something like:
> > 
> > location / {  
> > proxy\_pass [http://127.0.0.1:3000](http://127.0.0.1:3000);  
> > error\_page 502 @502;  
> > }

It is possible, you should use the proxy\_intercept\_errors directive:

location / {  
proxy\_pass [http://127.0.0.1:3000](http://127.0.0.1:3000);  
proxy\_intercept\_errors on;  
error\_page 502 @502;  
}

location @502 {  
# all named locations are internal by default, hence no “internal;”  
return 502 “Gateway error while servicing $request\_uri!\n”;  
}

Max

---

<div class="post-metadata">

**Author:** ![ewildgoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@ewildgoose](https://www.ruby-forum.com/u/ewildgoose)\
**Post date:** [March 6, 2012, 11:33pm UTC](https://www.ruby-forum.com/t/using-error-page-to-a-named-location-possible/217612/7 "2012-03-06T23:33:30Z")

</div>

On 06/03/2012 17:47, Maxim D. wrote:

> > 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?

Many thanks!

Ed W

---

<div class="post-metadata">

**Author:** ![ewildgoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@ewildgoose](https://www.ruby-forum.com/u/ewildgoose)\
**Post date:** [March 7, 2012, 12:29am UTC](https://www.ruby-forum.com/t/using-error-page-to-a-named-location-possible/217612/8 "2012-03-07T00:29:20Z")

</div>

Hello!

On Tue, Mar 06, 2012 at 10:32:56PM +0000, Ed W wrote:

> > > root /var/www;  
> > > This should work at least for GET requests.
> 
> 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:

> **[How nginx processes a request](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, + . 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 + + 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

The (2) is more like a hack, but should work as [//502.html](https://502.html) isn’t  
normally reachable via nginx due to merge\_slashes being “on” by  
default (see [Module ngx\_http\_core\_module](http://nginx.org/r/merge_slashes)).

Maxim D.

---

<div class="post-metadata">

**Author:** ![ewildgoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@ewildgoose](https://www.ruby-forum.com/u/ewildgoose)\
**Post date:** [March 7, 2012, 10:55am UTC](https://www.ruby-forum.com/t/using-error-page-to-a-named-location-possible/217612/9 "2012-03-07T10:55:27Z")

</div>

On 06/03/2012 23:28, Maxim D. wrote:

> > > > }  
> > > > root /var/www;  
> > > > The key seems to be the rewrite clause - near as I can see, without  
> > > > will behave much like normal static location, as described here:  
> > > > generate 404.
> 
> 1. 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:

Hi, Thanks for this REALLY clear post. I wonder if there is somewhere  
sensible to record this on the wiki - it’s very incisive on a subtle  
subject!

Just to confirm my understanding, the point 2) above seems to the key -  
ie the “index” module is doing a “redirect” _without_ a break, hence  
adding the explicit redirect WITH a break is what we need to prevent the  
cycle. This fits with my observations (of course) because when I added  
a location matching “location /502.html” this also prevents the cycle

Thanks for investing quite some time answering this!

Note, the background to this is that I want to bounce any incoming url  
to “[http://portal/login?redirect\_to=$encoded\_incoming\_url](http://portal/login?redirect_to=$encoded_incoming_url)”. I have  
tried to achieve this using only core nginx, but I can’t handle the  
corner cases such as incoming url having multiple parameters. I have  
worked around using my cgi to generate the redirect. _IF_ you believe  
that this should be possible using only nginx I would be interested to  
re-ask that question - however, I think you are going to confirm that  
it’s not currently possible?

Many thanks again!

Ed W

---

<div class="post-metadata">

**Author:** ![ewildgoose](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@ewildgoose](https://www.ruby-forum.com/u/ewildgoose)\
**Post date:** [March 7, 2012, 12:40pm UTC](https://www.ruby-forum.com/t/using-error-page-to-a-named-location-possible/217612/10 "2012-03-07T12:40:16Z")

</div>

2012/3/7 Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> > > ```
> > > location @502 {
> > > internal;
> > > root /var/www;
> > > rewrite ^ /502.html break;
> > > }
> > > 
> > > ```

This seems to be working, too:

location @502 {  
root /var/www;  
try\_files /502.html =404;  
}
