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) {