Mercurial > hg > nginx-quic
comparison src/http/ngx_http_upstream.c @ 7188:93abb5a855d6
Upstream: fixed "header already sent" alerts on backend errors.
Following ad3f342f14ba046c (1.9.13), it is possible that a request where
header was already sent will be finalized with NGX_HTTP_BAD_GATEWAY,
triggering an attempt to return additional error response and the
"header already sent" alert as a result.
In particular, it is trivial to reproduce the problem with a HEAD request
and caching enabled. With caching enabled nginx will change HEAD to GET
and will set u->pipe->downstream_error to suppress sending the response
body to the client. When a backend-related error occurs (for example,
proxy_read_timeout expires), ngx_http_finalize_upstream_request() will
be called with NGX_HTTP_BAD_GATEWAY. After ad3f342f14ba046c this will
result in ngx_http_finalize_request(NGX_HTTP_BAD_GATEWAY).
Fix is to move u->pipe->downstream_error handling to a later point,
where all special response codes are changed to NGX_ERROR.
Reported by Jan Prachar,
http://mailman.nginx.org/pipermail/nginx-devel/2018-January/010737.html.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 11 Jan 2018 21:43:49 +0300 |
parents | 84e53e4735a4 |
children | 0b72d545f098 |
comparison
equal
deleted
inserted
replaced
7187:c6cc8db553eb | 7188:93abb5a855d6 |
---|---|
4372 | 4372 |
4373 r->connection->log->action = "sending to client"; | 4373 r->connection->log->action = "sending to client"; |
4374 | 4374 |
4375 if (!u->header_sent | 4375 if (!u->header_sent |
4376 || rc == NGX_HTTP_REQUEST_TIME_OUT | 4376 || rc == NGX_HTTP_REQUEST_TIME_OUT |
4377 || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST | 4377 || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST) |
4378 || (u->pipe && u->pipe->downstream_error)) | |
4379 { | 4378 { |
4380 ngx_http_finalize_request(r, rc); | 4379 ngx_http_finalize_request(r, rc); |
4381 return; | 4380 return; |
4382 } | 4381 } |
4383 | 4382 |
4386 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | 4385 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { |
4387 rc = NGX_ERROR; | 4386 rc = NGX_ERROR; |
4388 flush = 1; | 4387 flush = 1; |
4389 } | 4388 } |
4390 | 4389 |
4391 if (r->header_only) { | 4390 if (r->header_only |
4391 || (u->pipe && u->pipe->downstream_error)) | |
4392 { | |
4392 ngx_http_finalize_request(r, rc); | 4393 ngx_http_finalize_request(r, rc); |
4393 return; | 4394 return; |
4394 } | 4395 } |
4395 | 4396 |
4396 if (rc == 0) { | 4397 if (rc == 0) { |