comparison 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
comparison
equal deleted inserted replaced
639:b516b4e38bc9 640:eb208e0cf44d
70 static void ngx_http_upstream_finalize_request(ngx_http_request_t *r, 70 static void ngx_http_upstream_finalize_request(ngx_http_request_t *r,
71 ngx_http_upstream_t *u, ngx_int_t rc); 71 ngx_http_upstream_t *u, ngx_int_t rc);
72 72
73 static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r, 73 static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
74 ngx_table_elt_t *h, ngx_uint_t offset); 74 ngx_table_elt_t *h, ngx_uint_t offset);
75 static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r,
76 ngx_table_elt_t *h, ngx_uint_t offset);
75 static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, 77 static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
76 ngx_table_elt_t *h, ngx_uint_t offset); 78 ngx_table_elt_t *h, ngx_uint_t offset);
77 static ngx_int_t 79 static ngx_int_t
78 ngx_http_upstream_process_cache_control(ngx_http_request_t *r, 80 ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
79 ngx_table_elt_t *h, ngx_uint_t offset); 81 ngx_table_elt_t *h, ngx_uint_t offset);
87 ngx_table_elt_t *h, ngx_uint_t offset); 89 ngx_table_elt_t *h, ngx_uint_t offset);
88 static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r, 90 static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r,
89 ngx_table_elt_t *h, ngx_uint_t offset); 91 ngx_table_elt_t *h, ngx_uint_t offset);
90 static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r, 92 static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r,
91 ngx_table_elt_t *h, ngx_uint_t offset); 93 ngx_table_elt_t *h, ngx_uint_t offset);
94 static ngx_int_t ngx_http_upstream_process_connection(ngx_http_request_t *r,
95 ngx_table_elt_t *h, ngx_uint_t offset);
96 static ngx_int_t
97 ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
98 ngx_table_elt_t *h, ngx_uint_t offset);
92 static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r, 99 static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
93 ngx_table_elt_t *h, ngx_uint_t offset); 100 ngx_table_elt_t *h, ngx_uint_t offset);
94 static ngx_int_t 101 static ngx_int_t
95 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r, 102 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
96 ngx_table_elt_t *h, ngx_uint_t offset); 103 ngx_table_elt_t *h, ngx_uint_t offset);
97 static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r, 104 static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r,
98 ngx_table_elt_t *h, ngx_uint_t offset);
99 static ngx_int_t ngx_http_upstream_copy_content_length(ngx_http_request_t *r,
100 ngx_table_elt_t *h, ngx_uint_t offset); 105 ngx_table_elt_t *h, ngx_uint_t offset);
101 static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, 106 static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r,
102 ngx_table_elt_t *h, ngx_uint_t offset); 107 ngx_table_elt_t *h, ngx_uint_t offset);
103 static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r, 108 static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r,
104 ngx_table_elt_t *h, ngx_uint_t offset); 109 ngx_table_elt_t *h, ngx_uint_t offset);
147 ngx_http_upstream_process_header_line, 152 ngx_http_upstream_process_header_line,
148 offsetof(ngx_http_upstream_headers_in_t, content_type), 153 offsetof(ngx_http_upstream_headers_in_t, content_type),
149 ngx_http_upstream_copy_content_type, 0, 1 }, 154 ngx_http_upstream_copy_content_type, 0, 1 },
150 155
151 { ngx_string("Content-Length"), 156 { ngx_string("Content-Length"),
152 ngx_http_upstream_process_header_line, 157 ngx_http_upstream_process_content_length,
153 offsetof(ngx_http_upstream_headers_in_t, content_length), 158 offsetof(ngx_http_upstream_headers_in_t, content_length),
154 ngx_http_upstream_copy_content_length, 0, 0 }, 159 ngx_http_upstream_ignore_header_line, 0, 0 },
155 160
156 { ngx_string("Date"), 161 { ngx_string("Date"),
157 ngx_http_upstream_process_header_line, 162 ngx_http_upstream_process_header_line,
158 offsetof(ngx_http_upstream_headers_in_t, date), 163 offsetof(ngx_http_upstream_headers_in_t, date),
159 ngx_http_upstream_copy_header_line, 164 ngx_http_upstream_copy_header_line,
213 offsetof(ngx_http_upstream_headers_in_t, accept_ranges), 218 offsetof(ngx_http_upstream_headers_in_t, accept_ranges),
214 ngx_http_upstream_copy_allow_ranges, 219 ngx_http_upstream_copy_allow_ranges,
215 offsetof(ngx_http_headers_out_t, accept_ranges), 1 }, 220 offsetof(ngx_http_headers_out_t, accept_ranges), 1 },
216 221
217 { ngx_string("Connection"), 222 { ngx_string("Connection"),
218 ngx_http_upstream_ignore_header_line, 0, 223 ngx_http_upstream_process_connection, 0,
219 ngx_http_upstream_ignore_header_line, 0, 0 }, 224 ngx_http_upstream_ignore_header_line, 0, 0 },
220 225
221 { ngx_string("Keep-Alive"), 226 { ngx_string("Keep-Alive"),
222 ngx_http_upstream_ignore_header_line, 0, 227 ngx_http_upstream_ignore_header_line, 0,
223 ngx_http_upstream_ignore_header_line, 0, 0 }, 228 ngx_http_upstream_ignore_header_line, 0, 0 },
244 ngx_http_upstream_copy_header_line, 0, 0 }, 249 ngx_http_upstream_copy_header_line, 0, 0 },
245 250
246 { ngx_string("X-Accel-Charset"), 251 { ngx_string("X-Accel-Charset"),
247 ngx_http_upstream_process_charset, 0, 252 ngx_http_upstream_process_charset, 0,
248 ngx_http_upstream_copy_header_line, 0, 0 }, 253 ngx_http_upstream_copy_header_line, 0, 0 },
254
255 { ngx_string("Transfer-Encoding"),
256 ngx_http_upstream_process_transfer_encoding, 0,
257 ngx_http_upstream_ignore_header_line, 0, 0 },
249 258
250 #if (NGX_HTTP_GZIP) 259 #if (NGX_HTTP_GZIP)
251 { ngx_string("Content-Encoding"), 260 { ngx_string("Content-Encoding"),
252 ngx_http_upstream_process_header_line, 261 ngx_http_upstream_process_header_line,
253 offsetof(ngx_http_upstream_headers_in_t, content_encoding), 262 offsetof(ngx_http_upstream_headers_in_t, content_encoding),
394 403
395 #if (NGX_HTTP_CACHE) 404 #if (NGX_HTTP_CACHE)
396 r->cache = NULL; 405 r->cache = NULL;
397 #endif 406 #endif
398 407
408 u->headers_in.content_length_n = -1;
409
399 return NGX_OK; 410 return NGX_OK;
400 } 411 }
401 412
402 413
403 void 414 void
798 809
799 u->buffer = *c->buf; 810 u->buffer = *c->buf;
800 u->buffer.pos += c->header_start; 811 u->buffer.pos += c->header_start;
801 812
802 ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t)); 813 ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
814 u->headers_in.content_length_n = -1;
803 815
804 if (ngx_list_init(&u->headers_in.headers, r->pool, 8, 816 if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
805 sizeof(ngx_table_elt_t)) 817 sizeof(ngx_table_elt_t))
806 != NGX_OK) 818 != NGX_OK)
807 { 819 {
1134 u->read_event_handler = ngx_http_upstream_process_header; 1146 u->read_event_handler = ngx_http_upstream_process_header;
1135 1147
1136 c->sendfile &= r->connection->sendfile; 1148 c->sendfile &= r->connection->sendfile;
1137 u->output.sendfile = c->sendfile; 1149 u->output.sendfile = c->sendfile;
1138 1150
1139 c->pool = r->pool; 1151 if (c->pool == NULL) {
1152
1153 /* we need separate pool here to be able to cache SSL connections */
1154
1155 c->pool = ngx_create_pool(128, r->connection->log);
1156 if (c->pool == NULL) {
1157 ngx_http_upstream_finalize_request(r, u,
1158 NGX_HTTP_INTERNAL_SERVER_ERROR);
1159 return;
1160 }
1161 }
1162
1140 c->log = r->connection->log; 1163 c->log = r->connection->log;
1164 c->pool->log = c->log;
1141 c->read->log = c->log; 1165 c->read->log = c->log;
1142 c->write->log = c->log; 1166 c->write->log = c->log;
1143 1167
1144 /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */ 1168 /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
1145 1169
1280 1304
1281 if (u->reinit_request(r) != NGX_OK) { 1305 if (u->reinit_request(r) != NGX_OK) {
1282 return NGX_ERROR; 1306 return NGX_ERROR;
1283 } 1307 }
1284 1308
1309 u->keepalive = 0;
1310
1285 ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t)); 1311 ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
1312 u->headers_in.content_length_n = -1;
1286 1313
1287 if (ngx_list_init(&u->headers_in.headers, r->pool, 8, 1314 if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
1288 sizeof(ngx_table_elt_t)) 1315 sizeof(ngx_table_elt_t))
1289 != NGX_OK) 1316 != NGX_OK)
1290 { 1317 {
1922 } 1949 }
1923 1950
1924 r->headers_out.status = u->headers_in.status_n; 1951 r->headers_out.status = u->headers_in.status_n;
1925 r->headers_out.status_line = u->headers_in.status_line; 1952 r->headers_out.status_line = u->headers_in.status_line;
1926 1953
1927 u->headers_in.content_length_n = r->headers_out.content_length_n; 1954 r->headers_out.content_length_n = u->headers_in.content_length_n;
1928 1955
1929 if (r->headers_out.content_length_n != -1) { 1956 u->length = u->headers_in.content_length_n;
1930 u->length = (size_t) r->headers_out.content_length_n;
1931
1932 } else {
1933 u->length = NGX_MAX_SIZE_T_VALUE;
1934 }
1935 1957
1936 return NGX_OK; 1958 return NGX_OK;
1937 } 1959 }
1938 1960
1939 1961
1991 } 2013 }
1992 2014
1993 if (!rev->ready) { 2015 if (!rev->ready) {
1994 break; 2016 break;
1995 } 2017 }
2018 }
2019
2020 if (u->length == 0) {
2021 ngx_http_upstream_finalize_request(r, u, 0);
2022 return;
1996 } 2023 }
1997 2024
1998 if (ngx_handle_read_event(rev, 0) != NGX_OK) { 2025 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1999 ngx_http_upstream_finalize_request(r, u, NGX_ERROR); 2026 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
2000 return; 2027 return;
2113 if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) { 2140 if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) {
2114 ngx_http_upstream_finalize_request(r, u, 0); 2141 ngx_http_upstream_finalize_request(r, u, 0);
2115 return; 2142 return;
2116 } 2143 }
2117 2144
2118 if (u->peer.connection->read->ready) { 2145 if (u->peer.connection->read->ready || u->length == 0) {
2119 ngx_http_upstream_process_non_buffered_upstream(r, u); 2146 ngx_http_upstream_process_non_buffered_upstream(r, u);
2120 } 2147 }
2121 } 2148 }
2122 2149
2123 return; 2150 return;
2291 2318
2292 p->read_timeout = u->conf->read_timeout; 2319 p->read_timeout = u->conf->read_timeout;
2293 p->send_timeout = clcf->send_timeout; 2320 p->send_timeout = clcf->send_timeout;
2294 p->send_lowat = clcf->send_lowat; 2321 p->send_lowat = clcf->send_lowat;
2295 2322
2323 p->length = -1;
2324
2325 if (u->input_filter_init
2326 && u->input_filter_init(p->input_ctx) != NGX_OK)
2327 {
2328 ngx_http_upstream_finalize_request(r, u, 0);
2329 return;
2330 }
2331
2296 u->read_event_handler = ngx_http_upstream_process_upstream; 2332 u->read_event_handler = ngx_http_upstream_process_upstream;
2297 r->write_event_handler = ngx_http_upstream_process_downstream; 2333 r->write_event_handler = ngx_http_upstream_process_downstream;
2298 2334
2299 ngx_http_upstream_process_upstream(r, u); 2335 ngx_http_upstream_process_upstream(r, u);
2300 } 2336 }
2380 if (rc == NGX_ERROR) { 2416 if (rc == NGX_ERROR) {
2381 ngx_http_upstream_finalize_request(r, u, 0); 2417 ngx_http_upstream_finalize_request(r, u, 0);
2382 return; 2418 return;
2383 } 2419 }
2384 2420
2385 ngx_chain_update_chains(&u->free_bufs, &u->busy_bufs, 2421 ngx_chain_update_chains(r->pool, &u->free_bufs, &u->busy_bufs,
2386 &u->out_bufs, u->output.tag); 2422 &u->out_bufs, u->output.tag);
2387 } 2423 }
2388 2424
2389 if (u->busy_bufs == NULL) { 2425 if (u->busy_bufs == NULL) {
2390 2426
2401 } 2437 }
2402 } 2438 }
2403 2439
2404 size = b->end - b->last; 2440 size = b->end - b->last;
2405 2441
2406 if (size > u->length) {
2407 size = u->length;
2408 }
2409
2410 if (size && upstream->read->ready) { 2442 if (size && upstream->read->ready) {
2411 2443
2412 n = upstream->recv(upstream, b->last, size); 2444 n = upstream->recv(upstream, b->last, size);
2413 2445
2414 if (n == NGX_AGAIN) { 2446 if (n == NGX_AGAIN) {
2501 cl->buf->pos = b->last; 2533 cl->buf->pos = b->last;
2502 b->last += bytes; 2534 b->last += bytes;
2503 cl->buf->last = b->last; 2535 cl->buf->last = b->last;
2504 cl->buf->tag = u->output.tag; 2536 cl->buf->tag = u->output.tag;
2505 2537
2506 if (u->length == NGX_MAX_SIZE_T_VALUE) { 2538 if (u->length == -1) {
2507 return NGX_OK; 2539 return NGX_OK;
2508 } 2540 }
2509 2541
2510 u->length -= bytes; 2542 u->length -= bytes;
2511 2543
2810 } 2842 }
2811 2843
2812 if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) { 2844 if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) {
2813 status = 0; 2845 status = 0;
2814 2846
2847 /* TODO: inform balancer instead */
2848
2849 u->peer.tries++;
2850
2815 } else { 2851 } else {
2816 switch(ft_type) { 2852 switch(ft_type) {
2817 2853
2818 case NGX_HTTP_UPSTREAM_FT_TIMEOUT: 2854 case NGX_HTTP_UPSTREAM_FT_TIMEOUT:
2819 status = NGX_HTTP_GATEWAY_TIME_OUT; 2855 status = NGX_HTTP_GATEWAY_TIME_OUT;
2884 2920
2885 (void) ngx_ssl_shutdown(u->peer.connection); 2921 (void) ngx_ssl_shutdown(u->peer.connection);
2886 } 2922 }
2887 #endif 2923 #endif
2888 2924
2925 if (u->peer.connection->pool) {
2926 ngx_destroy_pool(u->peer.connection->pool);
2927 }
2928
2889 ngx_close_connection(u->peer.connection); 2929 ngx_close_connection(u->peer.connection);
2890 } 2930 }
2891 2931
2892 #if 0 2932 #if 0
2893 if (u->conf->busy_lock && !u->busy_locked) { 2933 if (u->conf->busy_lock && !u->busy_locked) {
2978 3018
2979 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 3019 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2980 "close http upstream connection: %d", 3020 "close http upstream connection: %d",
2981 u->peer.connection->fd); 3021 u->peer.connection->fd);
2982 3022
3023 if (u->peer.connection->pool) {
3024 ngx_destroy_pool(u->peer.connection->pool);
3025 }
3026
2983 ngx_close_connection(u->peer.connection); 3027 ngx_close_connection(u->peer.connection);
2984 } 3028 }
2985 3029
2986 u->peer.connection = NULL; 3030 u->peer.connection = NULL;
2987 3031
3053 3097
3054 static ngx_int_t 3098 static ngx_int_t
3055 ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, 3099 ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
3056 ngx_uint_t offset) 3100 ngx_uint_t offset)
3057 { 3101 {
3102 return NGX_OK;
3103 }
3104
3105
3106 static ngx_int_t
3107 ngx_http_upstream_process_content_length(ngx_http_request_t *r,
3108 ngx_table_elt_t *h, ngx_uint_t offset)
3109 {
3110 ngx_http_upstream_t *u;
3111
3112 u = r->upstream;
3113
3114 u->headers_in.content_length = h;
3115 u->headers_in.content_length_n = ngx_atoof(h->value.data, h->value.len);
3116
3058 return NGX_OK; 3117 return NGX_OK;
3059 } 3118 }
3060 3119
3061 3120
3062 static ngx_int_t 3121 static ngx_int_t
3319 return NGX_OK; 3378 return NGX_OK;
3320 } 3379 }
3321 3380
3322 3381
3323 static ngx_int_t 3382 static ngx_int_t
3383 ngx_http_upstream_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
3384 ngx_uint_t offset)
3385 {
3386 r->upstream->headers_in.connection = h;
3387
3388 if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
3389 (u_char *) "close", 5 - 1)
3390 != NULL)
3391 {
3392 r->upstream->headers_in.connection_close = 1;
3393 }
3394
3395 return NGX_OK;
3396 }
3397
3398
3399 static ngx_int_t
3400 ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
3401 ngx_table_elt_t *h, ngx_uint_t offset)
3402 {
3403 r->upstream->headers_in.transfer_encoding = h;
3404
3405 if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
3406 (u_char *) "chunked", 7 - 1)
3407 != NULL)
3408 {
3409 r->upstream->headers_in.chunked = 1;
3410 }
3411
3412 return NGX_OK;
3413 }
3414
3415
3416 static ngx_int_t
3324 ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, 3417 ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
3325 ngx_uint_t offset) 3418 ngx_uint_t offset)
3326 { 3419 {
3327 ngx_table_elt_t *ho, **ph; 3420 ngx_table_elt_t *ho, **ph;
3328 3421
3420 r->headers_out.charset.len = last - p; 3513 r->headers_out.charset.len = last - p;
3421 r->headers_out.charset.data = p; 3514 r->headers_out.charset.data = p;
3422 3515
3423 return NGX_OK; 3516 return NGX_OK;
3424 } 3517 }
3425
3426 return NGX_OK;
3427 }
3428
3429
3430 static ngx_int_t
3431 ngx_http_upstream_copy_content_length(ngx_http_request_t *r, ngx_table_elt_t *h,
3432 ngx_uint_t offset)
3433 {
3434 ngx_table_elt_t *ho;
3435
3436 ho = ngx_list_push(&r->headers_out.headers);
3437 if (ho == NULL) {
3438 return NGX_ERROR;
3439 }
3440
3441 *ho = *h;
3442
3443 r->headers_out.content_length = ho;
3444 r->headers_out.content_length_n = ngx_atoof(h->value.data, h->value.len);
3445 3518
3446 return NGX_OK; 3519 return NGX_OK;
3447 } 3520 }
3448 3521
3449 3522