Mercurial > hg > nginx-vendor-current
diff src/http/ngx_http_upstream.c @ 640:eb208e0cf44d NGINX_1_1_4
nginx 1.1.4
*) Feature: the ngx_http_upstream_keepalive module.
*) Feature: the "proxy_http_version" directive.
*) Feature: the "fastcgi_keep_conn" directive.
*) Feature: the "worker_aio_requests" directive.
*) Bugfix: if nginx was built --with-file-aio it could not be run on
Linux kernel which did not support AIO.
*) Bugfix: in Linux AIO error processing.
Thanks to Hagai Avrahami.
*) Bugfix: reduced memory consumption for long-lived requests.
*) Bugfix: the module ngx_http_mp4_module did not support 64-bit MP4
"co64" atom.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Tue, 20 Sep 2011 00:00:00 +0400 |
parents | 5b73504dd4ba |
children | d3cf6c6b0043 |
line wrap: on
line diff
--- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -72,6 +72,8 @@ static void ngx_http_upstream_finalize_r static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t @@ -89,6 +91,11 @@ static ngx_int_t ngx_http_upstream_proce ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_connection(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t + ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t @@ -96,8 +103,6 @@ static ngx_int_t ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); -static ngx_int_t ngx_http_upstream_copy_content_length(ngx_http_request_t *r, - ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r, @@ -149,9 +154,9 @@ ngx_http_upstream_header_t ngx_http_ups ngx_http_upstream_copy_content_type, 0, 1 }, { ngx_string("Content-Length"), - ngx_http_upstream_process_header_line, + ngx_http_upstream_process_content_length, offsetof(ngx_http_upstream_headers_in_t, content_length), - ngx_http_upstream_copy_content_length, 0, 0 }, + ngx_http_upstream_ignore_header_line, 0, 0 }, { ngx_string("Date"), ngx_http_upstream_process_header_line, @@ -215,7 +220,7 @@ ngx_http_upstream_header_t ngx_http_ups offsetof(ngx_http_headers_out_t, accept_ranges), 1 }, { ngx_string("Connection"), - ngx_http_upstream_ignore_header_line, 0, + ngx_http_upstream_process_connection, 0, ngx_http_upstream_ignore_header_line, 0, 0 }, { ngx_string("Keep-Alive"), @@ -247,6 +252,10 @@ ngx_http_upstream_header_t ngx_http_ups ngx_http_upstream_process_charset, 0, ngx_http_upstream_copy_header_line, 0, 0 }, + { ngx_string("Transfer-Encoding"), + ngx_http_upstream_process_transfer_encoding, 0, + ngx_http_upstream_ignore_header_line, 0, 0 }, + #if (NGX_HTTP_GZIP) { ngx_string("Content-Encoding"), ngx_http_upstream_process_header_line, @@ -396,6 +405,8 @@ ngx_http_upstream_create(ngx_http_reques r->cache = NULL; #endif + u->headers_in.content_length_n = -1; + return NGX_OK; } @@ -800,6 +811,7 @@ ngx_http_upstream_cache_send(ngx_http_re u->buffer.pos += c->header_start; ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t)); + u->headers_in.content_length_n = -1; if (ngx_list_init(&u->headers_in.headers, r->pool, 8, sizeof(ngx_table_elt_t)) @@ -1136,8 +1148,20 @@ ngx_http_upstream_connect(ngx_http_reque c->sendfile &= r->connection->sendfile; u->output.sendfile = c->sendfile; - c->pool = r->pool; + if (c->pool == NULL) { + + /* we need separate pool here to be able to cache SSL connections */ + + c->pool = ngx_create_pool(128, r->connection->log); + if (c->pool == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + } + c->log = r->connection->log; + c->pool->log = c->log; c->read->log = c->log; c->write->log = c->log; @@ -1282,7 +1306,10 @@ ngx_http_upstream_reinit(ngx_http_reques return NGX_ERROR; } + u->keepalive = 0; + ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t)); + u->headers_in.content_length_n = -1; if (ngx_list_init(&u->headers_in.headers, r->pool, 8, sizeof(ngx_table_elt_t)) @@ -1924,14 +1951,9 @@ ngx_http_upstream_process_headers(ngx_ht r->headers_out.status = u->headers_in.status_n; r->headers_out.status_line = u->headers_in.status_line; - u->headers_in.content_length_n = r->headers_out.content_length_n; - - if (r->headers_out.content_length_n != -1) { - u->length = (size_t) r->headers_out.content_length_n; - - } else { - u->length = NGX_MAX_SIZE_T_VALUE; - } + r->headers_out.content_length_n = u->headers_in.content_length_n; + + u->length = u->headers_in.content_length_n; return NGX_OK; } @@ -1995,6 +2017,11 @@ ngx_http_upstream_process_body_in_memory } } + if (u->length == 0) { + ngx_http_upstream_finalize_request(r, u, 0); + return; + } + if (ngx_handle_read_event(rev, 0) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, NGX_ERROR); return; @@ -2115,7 +2142,7 @@ ngx_http_upstream_send_response(ngx_http return; } - if (u->peer.connection->read->ready) { + if (u->peer.connection->read->ready || u->length == 0) { ngx_http_upstream_process_non_buffered_upstream(r, u); } } @@ -2293,6 +2320,15 @@ ngx_http_upstream_send_response(ngx_http p->send_timeout = clcf->send_timeout; p->send_lowat = clcf->send_lowat; + p->length = -1; + + if (u->input_filter_init + && u->input_filter_init(p->input_ctx) != NGX_OK) + { + ngx_http_upstream_finalize_request(r, u, 0); + return; + } + u->read_event_handler = ngx_http_upstream_process_upstream; r->write_event_handler = ngx_http_upstream_process_downstream; @@ -2382,7 +2418,7 @@ ngx_http_upstream_process_non_buffered_r return; } - ngx_chain_update_chains(&u->free_bufs, &u->busy_bufs, + ngx_chain_update_chains(r->pool, &u->free_bufs, &u->busy_bufs, &u->out_bufs, u->output.tag); } @@ -2403,10 +2439,6 @@ ngx_http_upstream_process_non_buffered_r size = b->end - b->last; - if (size > u->length) { - size = u->length; - } - if (size && upstream->read->ready) { n = upstream->recv(upstream, b->last, size); @@ -2503,7 +2535,7 @@ ngx_http_upstream_non_buffered_filter(vo cl->buf->last = b->last; cl->buf->tag = u->output.tag; - if (u->length == NGX_MAX_SIZE_T_VALUE) { + if (u->length == -1) { return NGX_OK; } @@ -2812,6 +2844,10 @@ ngx_http_upstream_next(ngx_http_request_ if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) { status = 0; + /* TODO: inform balancer instead */ + + u->peer.tries++; + } else { switch(ft_type) { @@ -2886,6 +2922,10 @@ ngx_http_upstream_next(ngx_http_request_ } #endif + if (u->peer.connection->pool) { + ngx_destroy_pool(u->peer.connection->pool); + } + ngx_close_connection(u->peer.connection); } @@ -2980,6 +3020,10 @@ ngx_http_upstream_finalize_request(ngx_h "close http upstream connection: %d", u->peer.connection->fd); + if (u->peer.connection->pool) { + ngx_destroy_pool(u->peer.connection->pool); + } + ngx_close_connection(u->peer.connection); } @@ -3060,6 +3104,21 @@ ngx_http_upstream_ignore_header_line(ngx static ngx_int_t +ngx_http_upstream_process_content_length(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + ngx_http_upstream_t *u; + + u = r->upstream; + + u->headers_in.content_length = h; + u->headers_in.content_length_n = ngx_atoof(h->value.data, h->value.len); + + return NGX_OK; +} + + +static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { @@ -3321,6 +3380,40 @@ ngx_http_upstream_process_charset(ngx_ht static ngx_int_t +ngx_http_upstream_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + r->upstream->headers_in.connection = h; + + if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len, + (u_char *) "close", 5 - 1) + != NULL) + { + r->upstream->headers_in.connection_close = 1; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + r->upstream->headers_in.transfer_encoding = h; + + if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len, + (u_char *) "chunked", 7 - 1) + != NULL) + { + r->upstream->headers_in.chunked = 1; + } + + return NGX_OK; +} + + +static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { @@ -3428,26 +3521,6 @@ ngx_http_upstream_copy_content_type(ngx_ static ngx_int_t -ngx_http_upstream_copy_content_length(ngx_http_request_t *r, ngx_table_elt_t *h, - ngx_uint_t offset) -{ - ngx_table_elt_t *ho; - - ho = ngx_list_push(&r->headers_out.headers); - if (ho == NULL) { - return NGX_ERROR; - } - - *ho = *h; - - r->headers_out.content_length = ho; - r->headers_out.content_length_n = ngx_atoof(h->value.data, h->value.len); - - return NGX_OK; -} - - -static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) {