Catching 408 response from upstream server

Hi,
I’m using nginx as reversed proxy, using the proxy module.
Whenever i get a response code >= 400 from the upstream server, i’m
redirecting the client to a different url.

This is the configuration i use (simplified):

    location ~ "^/proxy/host_(.*)/fallback_(.*)" {

        proxy_pass http://$1;

        proxy_intercept_errors on;
        error_page 404 408 500 http://$2;
    }

However, i’ve noticed that when the upstream server responds with 408
response code, nginx does not send a redirect.
Instead it terminates the connection to the client.

Is this the intended behavior?
Is there any way around it?
I’d like to be able to intercept 408 responses as well and redirect
them.
Any alternative suggestions to implement it are very welcome.

Thanks in advance,
Shmulikb

Posted at Nginx Forum:

I do not see anything in error_page
http://nginx.org/en/docs/http/ngx_http_core_module.html#error_page
documentation stating it would not send anything for 408.
I suggest a problem on your side.

Do you have HTTP Requests/Responses traces to show?
Any sign of trouble (configuration, not applied, wrong location, empty
arguments, etc.)?

B. R.

Hi,
On 02/10/2015 08:35 AM, shmulik wrote:

         proxy_intercept_errors on;
         error_page 404 408 500 http://$2;
     }

However, i’ve noticed that when the upstream server responds with 408
response code, nginx does not send a redirect.
Instead it terminates the connection to the client.

I think this is because of the nature of 408 error. It means the client
is slow, (or slowloris). Probably the only sane thing to do in that case
is to drop with an error. Though, looking at the documentation it seems
you can configure when a request is slow with this directives:

client_body_timeout
client_header_timeout

Check her e for more details:

client_header_timeout

Is this the intended behavior?
Is there any way around it?

See above

[email protected]
nginx Info Page

Regards,
Frederik

Thank you.
As i wrote in reply to B. R., i’m trying to catch an 408 response from
an
upstream server, and turn it into a 302 redirect.
Since the upstream is the one answering with 408, i cannot control its
logic
by tweaking Nginx configuration.

In my scenario, the client is “fast enough”, as Nginx accepts its
request
and sends a request to the upstream.
So theoretically Ngnix should consider the client “fast enough” to
answer to
it.

So i still believe it should be valid to intercept this 408 response
from
upstream and turn in into a different response toward the client (302 in
my
case).

Still, i accept the fact that my logic might be wrong, and i’m open to
hear
alternative reasoning.

Thanks,
Shmulik

Posted at Nginx Forum:

Hi,

Below is the debug_http log showing the same location handling upstream
response of 409, and next of 408.
You can see that the 408 response is handled differently:

// ----------------409 -------------- //

2015/02/11 22:07:03 [debug] 20611#0: *3 http upstream process header

2015/02/11 22:07:03 [debug] 20611#0: *3 http proxy header done

2015/02/11 22:07:03 [debug] 20611#0: *3 finalize http upstream request:
409
2015/02/11 22:07:03 [debug] 20611#0: *3 finalize http proxy request
2015/02/11 22:07:03 [debug] 20611#0: *3 free rr peer 1 0
2015/02/11 22:07:03 [debug] 20611#0: *3 close http upstream connection:
12
2015/02/11 22:07:03 [debug] 20611#0: *3 http finalize request: 409,
“/proxy/host_www.a.com/fallback_www.b.com/” a:1, c:1
2015/02/11 22:07:03 [debug] 20611#0: *3 http special response: 409,
“/proxy/host_www.a.com/fallback_www.b.com/” // ← handled as special
response
2015/02/11 22:07:03 [debug] 20611#0: *3 http script var:
http://www.b.com/
2015/02/11 22:07:03 [debug] 20611#0: *3 http log handler
2015/02/11 22:07:03 [debug] 20611#0: *3 HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Wed, 11 Feb 2015 20:07:03 GMT
Content-Type: text/html
Content-Length: 149
Connection: keep-alive
Location: http://www.b.com/

// ------------- 408 -------------- //

2015/02/11 22:05:03 [debug] 20611#0: *1 http upstream process header
2015/02/11 22:05:03 [debug] 20611#0: *1 http proxy header done
2015/02/11 22:05:03 [debug] 20611#0: *1 finalize http upstream request:
408
2015/02/11 22:05:03 [debug] 20611#0: *1 finalize http proxy request
2015/02/11 22:05:03 [debug] 20611#0: *1 free rr peer 1 0
2015/02/11 22:05:03 [debug] 20611#0: *1 close http upstream connection:
12
2015/02/11 22:05:03 [debug] 20611#0: *1 http finalize request: 408,
“/proxy/host_www.a.com/fallback_www.b.com/” a:1, c:1
2015/02/11 22:05:03 [debug] 20611#0: *1 http terminate request count:1
//
← handled by terminating the connection
2015/02/11 22:05:03 [debug] 20611#0: *1 http terminate cleanup count:1
blk:0
2015/02/11 22:05:03 [debug] 20611#0: *1 http posted request:
“/proxy/host_www.a.com/fallback_www.b.com/”
2015/02/11 22:05:03 [debug] 20611#0: *1 http terminate handler count:1
2015/02/11 22:05:03 [debug] 20611#0: *1 http request count:1 blk:0
2015/02/11 22:05:03 [debug] 20611#0: *1 http close request

I’ve tried to follow this in code (by the way, i’m using version 1.6.2,
sorry i didn’t mention it earlier).
It seems that indeed response code 408 is handled differently. in
function
“ngx_http_finalize_request” i can see that code 408 is handled by
calling
“ngx_http_terminate_request”, while other codes (like 409) are handled a
few
lines later with “ngx_http_special_response_handler” which also handles
the
error_page directive.

I’ve read in a different post in this forum that Nginx, by design,
terminates the connection when it’s configured to respond with 408
response
code - for example when using “return 408” in a location. The post can
be
found here: Re: return 408 does not return body and status = 200

However in my case, i’m not generating an 408 response in Nginx. I’m
trying
to catch an 408 response from the upstream server, and turn it into a
redirect.

As you said, the documentation doesn’t say anything about error_page
handling response code 408 differently, so i can’t figure out if this
behavior is intentional or not.

If intentional - i’d really like to understand the logic behind it,
perhaps
i’m looking at it all wrong.
If it’s not intentional - i’d really like to find a way around this, to
return a redirect to the client.

Thank you for your patience and help,
ShmulikB

Posted at Nginx Forum:

Hi,

Below is the debug_http log showing the same location handling upstream
response of 409, and next of 408.
You can see that the 408 response is handled differently:

// ----------------409 -------------- //

2015/02/11 22:07:03 [debug] 20611#0: *3 http upstream process header

2015/02/11 22:07:03 [debug] 20611#0: *3 http proxy header done

2015/02/11 22:07:03 [debug] 20611#0: *3 finalize http upstream request:
409
2015/02/11 22:07:03 [debug] 20611#0: *3 finalize http proxy request
2015/02/11 22:07:03 [debug] 20611#0: *3 free rr peer 1 0
2015/02/11 22:07:03 [debug] 20611#0: *3 close http upstream connection:
12
2015/02/11 22:07:03 [debug] 20611#0: *3 http finalize request: 409,
“/proxy/host_www.a.com/fallback_www.b.com/” a:1, c:1
2015/02/11 22:07:03 [debug] 20611#0: *3 http special response: 409,
“/proxy/host_www.a.com/fallback_www.b.com/” // ← handled as special
response
2015/02/11 22:07:03 [debug] 20611#0: *3 http script var:
http://www.b.com/
2015/02/11 22:07:03 [debug] 20611#0: *3 http log handler
2015/02/11 22:07:03 [debug] 20611#0: *3 HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Wed, 11 Feb 2015 20:07:03 GMT
Content-Type: text/html
Content-Length: 149
Connection: keep-alive
Location: http://www.b.com/

// ------------- 408 -------------- //

2015/02/11 22:05:03 [debug] 20611#0: *1 http upstream process header
2015/02/11 22:05:03 [debug] 20611#0: *1 http proxy header done
2015/02/11 22:05:03 [debug] 20611#0: *1 finalize http upstream request:
408
2015/02/11 22:05:03 [debug] 20611#0: *1 finalize http proxy request
2015/02/11 22:05:03 [debug] 20611#0: *1 free rr peer 1 0
2015/02/11 22:05:03 [debug] 20611#0: *1 close http upstream connection:
12
2015/02/11 22:05:03 [debug] 20611#0: *1 http finalize request: 408,
“/proxy/host_www.a.com/fallback_www.b.com/” a:1, c:1
2015/02/11 22:05:03 [debug] 20611#0: *1 http terminate request count:1
//
← handled by terminating the connection
2015/02/11 22:05:03 [debug] 20611#0: *1 http terminate cleanup count:1
blk:0
2015/02/11 22:05:03 [debug] 20611#0: *1 http posted request:
“/proxy/host_www.a.com/fallback_www.b.com/”
2015/02/11 22:05:03 [debug] 20611#0: *1 http terminate handler count:1
2015/02/11 22:05:03 [debug] 20611#0: *1 http request count:1 blk:0
2015/02/11 22:05:03 [debug] 20611#0: *1 http close request

I’ve tried to follow this in code (by the way, i’m using version 1.6.2,
sorry i didn’t mention it earlier).
It seems that indeed response code 408 is handled differently. in
function
“ngx_http_finalize_request” i can see that code 408 is handled by
calling
“ngx_http_terminate_request”, while other codes (like 409) are handled a
few
lines later with “ngx_http_special_response_handler” which also handles
the
error_page directive.

I’ve read in a different post in this forum that Nginx, by design,
terminates the connection when it’s configured to respond with 408
response
code - for example when using “return 408” in a location. The post can
be
found here: Re: return 408 does not return body and status = 200

However in my case, i’m not generating an 408 response in Nginx. I’m
trying
to catch an 408 response from the upstream server, and turn it into a
redirect.

As you said, the documentation doesn’t say anything about error_page
handling response code 408 differently, so i can’t figure out if this
behavior is intentional or not.

If intentional - i’d really like to understand the logic behind it,
perhaps
i’m looking at it all wrong.
If it’s not intentional - i’d really like to find a way around this, to
return a redirect to the client.

Thank you for your patience and help,
ShmulikB

Posted at Nginx Forum: