comparison src/http/ngx_http_upstream.c @ 464:c8cfb6c462ef NGINX_0_7_44

nginx 0.7.44 *) Feature: the ngx_http_proxy_module preliminary cache support. *) Feature: the --with-pcre option in the configure. *) Feature: the "try_files" directive is now allowed on the server block level. *) Bugfix: the "try_files" directive handled incorrectly a query string in a fallback parameter. *) Bugfix: the "try_files" directive might test incorrectly directories. *) Bugfix: if there is the single server for given address:port pair, then captures in regular expressions in a "server_name" directive did not work.
author Igor Sysoev <http://sysoev.ru>
date Mon, 23 Mar 2009 00:00:00 +0300
parents a8424ffa495c
children 09f0ef15d544
comparison
equal deleted inserted replaced
463:51cb914e6d3a 464:c8cfb6c462ef
6 6
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_http.h> 9 #include <ngx_http.h>
10 10
11
12 #if (NGX_HTTP_CACHE)
13 static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r,
14 ngx_http_upstream_t *u);
15 static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r,
16 ngx_http_upstream_t *u);
17 #endif
11 18
12 static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx); 19 static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx);
13 static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r); 20 static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r);
14 static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r); 21 static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r);
15 static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, 22 static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
27 static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r, 34 static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
28 ngx_http_upstream_t *u); 35 ngx_http_upstream_t *u);
29 static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r, 36 static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
30 ngx_http_upstream_t *u); 37 ngx_http_upstream_t *u);
31 static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c); 38 static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c);
39 static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r,
40 ngx_http_upstream_t *u);
32 static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r, 41 static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
33 ngx_http_upstream_t *u); 42 ngx_http_upstream_t *u);
34 static void ngx_http_upstream_send_response(ngx_http_request_t *r, 43 static void ngx_http_upstream_send_response(ngx_http_request_t *r,
35 ngx_http_upstream_t *u); 44 ngx_http_upstream_t *u);
36 static void 45 static void
78 ngx_table_elt_t *h, ngx_uint_t offset); 87 ngx_table_elt_t *h, ngx_uint_t offset);
79 static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r, 88 static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r,
80 ngx_table_elt_t *h, ngx_uint_t offset); 89 ngx_table_elt_t *h, ngx_uint_t offset);
81 static ngx_int_t ngx_http_upstream_copy_content_length(ngx_http_request_t *r, 90 static ngx_int_t ngx_http_upstream_copy_content_length(ngx_http_request_t *r,
82 ngx_table_elt_t *h, ngx_uint_t offset); 91 ngx_table_elt_t *h, ngx_uint_t offset);
92 static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r,
93 ngx_table_elt_t *h, ngx_uint_t offset);
83 static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r, 94 static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r,
84 ngx_table_elt_t *h, ngx_uint_t offset); 95 ngx_table_elt_t *h, ngx_uint_t offset);
85 static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, 96 static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r,
86 ngx_table_elt_t *h, ngx_uint_t offset); 97 ngx_table_elt_t *h, ngx_uint_t offset);
98 static ngx_int_t ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
99 ngx_table_elt_t *h, ngx_uint_t offset);
100
87 #if (NGX_HTTP_GZIP) 101 #if (NGX_HTTP_GZIP)
88 static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r, 102 static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
89 ngx_table_elt_t *h, ngx_uint_t offset); 103 ngx_table_elt_t *h, ngx_uint_t offset);
90 #endif 104 #endif
91 105
137 offsetof(ngx_http_headers_out_t, date), 0 }, 151 offsetof(ngx_http_headers_out_t, date), 0 },
138 152
139 { ngx_string("Last-Modified"), 153 { ngx_string("Last-Modified"),
140 ngx_http_upstream_process_header_line, 154 ngx_http_upstream_process_header_line,
141 offsetof(ngx_http_upstream_headers_in_t, last_modified), 155 offsetof(ngx_http_upstream_headers_in_t, last_modified),
142 ngx_http_upstream_copy_header_line, 156 ngx_http_upstream_copy_last_modified, 0, 0 },
143 offsetof(ngx_http_headers_out_t, last_modified), 0 },
144 157
145 { ngx_string("Server"), 158 { ngx_string("Server"),
146 ngx_http_upstream_process_header_line, 159 ngx_http_upstream_process_header_line,
147 offsetof(ngx_http_upstream_headers_in_t, server), 160 offsetof(ngx_http_upstream_headers_in_t, server),
148 ngx_http_upstream_copy_header_line, 161 ngx_http_upstream_copy_header_line,
183 offsetof(ngx_http_headers_out_t, expires), 1 }, 196 offsetof(ngx_http_headers_out_t, expires), 1 },
184 197
185 { ngx_string("Accept-Ranges"), 198 { ngx_string("Accept-Ranges"),
186 ngx_http_upstream_process_header_line, 199 ngx_http_upstream_process_header_line,
187 offsetof(ngx_http_upstream_headers_in_t, accept_ranges), 200 offsetof(ngx_http_upstream_headers_in_t, accept_ranges),
188 ngx_http_upstream_copy_header_line, 201 ngx_http_upstream_copy_allow_ranges,
189 offsetof(ngx_http_headers_out_t, accept_ranges), 1 }, 202 offsetof(ngx_http_headers_out_t, accept_ranges), 1 },
190 203
191 { ngx_string("Connection"), 204 { ngx_string("Connection"),
192 ngx_http_upstream_ignore_header_line, 0, 205 ngx_http_upstream_ignore_header_line, 0,
193 ngx_http_upstream_ignore_header_line, 0, 0 }, 206 ngx_http_upstream_ignore_header_line, 0, 0 },
358 371
359 if (r->request_body) { 372 if (r->request_body) {
360 u->request_bufs = r->request_body->bufs; 373 u->request_bufs = r->request_body->bufs;
361 } 374 }
362 375
376 #if (NGX_HTTP_CACHE)
377
378 if (u->conf->cache) {
379 ngx_int_t rc;
380
381 rc = ngx_http_upstream_cache(r, u);
382
383 if (rc == NGX_DONE) {
384 return;
385 }
386
387 if (rc != NGX_DECLINED) {
388 ngx_http_finalize_request(r, rc);
389 return;
390 }
391 }
392
393 #endif
394
363 if (u->create_request(r) != NGX_OK) { 395 if (u->create_request(r) != NGX_OK) {
364 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 396 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
365 return; 397 return;
366 } 398 }
367 399
487 return; 519 return;
488 } 520 }
489 521
490 ngx_http_upstream_connect(r, u); 522 ngx_http_upstream_connect(r, u);
491 } 523 }
524
525
526 #if (NGX_HTTP_CACHE)
527
528 static ngx_int_t
529 ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
530 {
531 ngx_int_t rc;
532 ngx_http_cache_t *c;
533
534 c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t));
535 if (c == NULL) {
536 return NGX_ERROR;
537 }
538
539 if (ngx_array_init(&c->keys, r->pool, 4, sizeof(ngx_str_t)) != NGX_OK) {
540 return NGX_ERROR;
541 }
542
543 r->cache = c;
544 c->file.log = r->connection->log;
545
546 if (u->create_key(r) != NGX_OK) {
547 return NGX_ERROR;
548 }
549
550 /* TODO: add keys */
551
552 ngx_http_file_cache_create_key(r);
553
554 u->cacheable = 1;
555
556 c->min_uses = r->upstream->conf->cache_min_uses;
557 c->body_start = r->upstream->conf->buffer_size;
558 c->file_cache = u->conf->cache->data;
559
560 rc = ngx_http_file_cache_open(r);
561
562 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
563 "http upstream cache: %i u:%ui", rc, c->uses);
564
565 if (rc == NGX_OK) {
566
567 rc = ngx_http_upstream_cache_send(r, u);
568
569 if (rc != NGX_HTTP_UPSTREAM_INVALID_HEADER) {
570 return rc;
571 }
572
573 } else if (rc == NGX_ERROR) {
574
575 return NGX_ERROR;
576
577 } else if (rc == NGX_HTTP_CACHE_STALE) {
578
579 u->stale_cache = 1;
580 u->buffer.start = NULL;
581
582 } else if (rc == NGX_DECLINED) {
583
584 if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) {
585 u->buffer.start = NULL;
586
587 } else {
588 u->buffer.pos = u->buffer.start + c->header_start;
589 u->buffer.last = u->buffer.pos;
590 }
591
592 } else if (rc == NGX_AGAIN) {
593
594 u->cacheable = 0;
595
596 } else {
597
598 /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */
599
600 return rc;
601 }
602
603 r->cached = 0;
604
605 return NGX_DECLINED;
606 }
607
608
609 static ngx_int_t
610 ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
611 {
612 ngx_int_t rc;
613 ngx_http_cache_t *c;
614
615 c = r->cache;
616
617 /* TODO: cache stack */
618
619 u->buffer = *c->buf;
620 u->buffer.pos += c->header_start;
621
622 ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
623
624 if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
625 sizeof(ngx_table_elt_t))
626 != NGX_OK)
627 {
628 return NGX_ERROR;
629 }
630
631 rc = u->process_header(r);
632
633 if (rc == NGX_OK) {
634
635 if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
636 return NGX_DONE;
637 }
638
639 return ngx_http_cache_send(r);
640 }
641
642 if (rc == NGX_ERROR) {
643 return NGX_ERROR;
644 }
645
646 /* rc == NGX_HTTP_UPSTREAM_INVALID_HEADER */
647
648 /* TODO: delete file */
649
650 return rc;
651 }
652
653 #endif
492 654
493 655
494 static void 656 static void
495 ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx) 657 ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
496 { 658 {
967 u->output.in = NULL; 1129 u->output.in = NULL;
968 u->output.busy = NULL; 1130 u->output.busy = NULL;
969 1131
970 /* reinit u->buffer */ 1132 /* reinit u->buffer */
971 1133
972 #if 0 1134 u->buffer.pos = u->buffer.start;
973 if (u->cache) { 1135
974 u->buffer.pos = u->buffer.start + u->cache->ctx.header_size; 1136 #if (NGX_HTTP_CACHE)
975 u->buffer.last = u->buffer.pos; 1137
976 1138 if (r->cache) {
977 } else { 1139 u->buffer.pos += r->cache->header_start;
978 u->buffer.pos = u->buffer.start; 1140 }
979 u->buffer.last = u->buffer.start;
980 }
981 #else
982
983 u->buffer.pos = u->buffer.start;
984 u->buffer.last = u->buffer.start;
985 1141
986 #endif 1142 #endif
1143
1144 u->buffer.last = u->buffer.pos;
987 1145
988 return NGX_OK; 1146 return NGX_OK;
989 } 1147 }
990 1148
991 1149
1113 1271
1114 1272
1115 static void 1273 static void
1116 ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u) 1274 ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
1117 { 1275 {
1118 ssize_t n; 1276 ssize_t n;
1119 ngx_int_t rc; 1277 ngx_int_t rc;
1120 ngx_str_t *uri, args; 1278 ngx_connection_t *c;
1121 ngx_uint_t i, flags;
1122 ngx_list_part_t *part;
1123 ngx_table_elt_t *h;
1124 ngx_connection_t *c;
1125 ngx_http_upstream_header_t *hh;
1126 ngx_http_upstream_main_conf_t *umcf;
1127 1279
1128 c = u->peer.connection; 1280 c = u->peer.connection;
1129 1281
1130 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, 1282 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1131 "http upstream process header"); 1283 "http upstream process header");
1164 ngx_http_upstream_finalize_request(r, u, 1316 ngx_http_upstream_finalize_request(r, u,
1165 NGX_HTTP_INTERNAL_SERVER_ERROR); 1317 NGX_HTTP_INTERNAL_SERVER_ERROR);
1166 return; 1318 return;
1167 } 1319 }
1168 1320
1169 #if 0 1321 #if (NGX_HTTP_CACHE)
1170 if (u->cache) { 1322
1171 u->buffer.pos += u->cache->ctx.header_size; 1323 if (r->cache) {
1324 u->buffer.pos += r->cache->header_start;
1172 u->buffer.last = u->buffer.pos; 1325 u->buffer.last = u->buffer.pos;
1173 } 1326 }
1174 #endif 1327 #endif
1175 } 1328 }
1176 1329
1255 if (ngx_http_upstream_intercept_errors(r, u) == NGX_OK) { 1408 if (ngx_http_upstream_intercept_errors(r, u) == NGX_OK) {
1256 return; 1409 return;
1257 } 1410 }
1258 } 1411 }
1259 1412
1260 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); 1413 if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
1261 1414 return;
1262 if (u->headers_in.x_accel_redirect) {
1263
1264 ngx_http_upstream_finalize_request(r, u, NGX_DECLINED);
1265
1266 part = &u->headers_in.headers.part;
1267 h = part->elts;
1268
1269 for (i = 0; /* void */; i++) {
1270
1271 if (i >= part->nelts) {
1272 if (part->next == NULL) {
1273 break;
1274 }
1275
1276 part = part->next;
1277 h = part->elts;
1278 i = 0;
1279 }
1280
1281 hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
1282 h[i].lowcase_key, h[i].key.len);
1283
1284 if (hh && hh->redirect) {
1285 if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
1286 ngx_http_finalize_request(r,
1287 NGX_HTTP_INTERNAL_SERVER_ERROR);
1288 return;
1289 }
1290 }
1291 }
1292
1293 uri = &u->headers_in.x_accel_redirect->value;
1294 args.len = 0;
1295 args.data = NULL;
1296 flags = 0;
1297
1298 if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
1299 ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
1300 return;
1301 }
1302
1303 if (flags & NGX_HTTP_ZERO_IN_URI) {
1304 r->zero_in_uri = 1;
1305 }
1306
1307 if (r->method != NGX_HTTP_HEAD) {
1308 r->method = NGX_HTTP_GET;
1309 }
1310
1311 r->valid_unparsed_uri = 0;
1312
1313 ngx_http_internal_redirect(r, uri, &args);
1314 return;
1315 }
1316
1317 part = &u->headers_in.headers.part;
1318 h = part->elts;
1319
1320 for (i = 0; /* void */; i++) {
1321
1322 if (i >= part->nelts) {
1323 if (part->next == NULL) {
1324 break;
1325 }
1326
1327 part = part->next;
1328 h = part->elts;
1329 i = 0;
1330 }
1331
1332 if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
1333 h[i].lowcase_key, h[i].key.len))
1334 {
1335 continue;
1336 }
1337
1338 hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
1339 h[i].lowcase_key, h[i].key.len);
1340
1341 if (hh) {
1342 if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
1343 ngx_http_upstream_finalize_request(r, u,
1344 NGX_HTTP_INTERNAL_SERVER_ERROR);
1345 return;
1346 }
1347
1348 continue;
1349 }
1350
1351 if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK) {
1352 ngx_http_upstream_finalize_request(r, u,
1353 NGX_HTTP_INTERNAL_SERVER_ERROR);
1354 return;
1355 }
1356 }
1357
1358 if (r->headers_out.server && r->headers_out.server->value.data == NULL) {
1359 r->headers_out.server->hash = 0;
1360 }
1361
1362 if (r->headers_out.date && r->headers_out.date->value.data == NULL) {
1363 r->headers_out.date->hash = 0;
1364 }
1365
1366 r->headers_out.status = u->headers_in.status_n;
1367 r->headers_out.status_line = u->headers_in.status_line;
1368
1369 u->headers_in.content_length_n = r->headers_out.content_length_n;
1370
1371 if (r->headers_out.content_length_n != -1) {
1372 u->length = (size_t) r->headers_out.content_length_n;
1373
1374 } else {
1375 u->length = NGX_MAX_SIZE_T_VALUE;
1376 } 1415 }
1377 1416
1378 if (!r->subrequest_in_memory) { 1417 if (!r->subrequest_in_memory) {
1379 ngx_http_upstream_send_response(r, u); 1418 ngx_http_upstream_send_response(r, u);
1380 return; 1419 return;
1441 return NGX_OK; 1480 return NGX_OK;
1442 } 1481 }
1443 1482
1444 #if (NGX_HTTP_CACHE) 1483 #if (NGX_HTTP_CACHE)
1445 1484
1446 if (u->peer.tries == 0 && u->stale && (u->conf->use_stale & un->mask)) { 1485 if (u->peer.tries == 0
1486 && u->stale_cache
1487 && (u->conf->cache_use_stale & un->mask))
1488 {
1447 ngx_http_upstream_finalize_request(r, u, 1489 ngx_http_upstream_finalize_request(r, u,
1448 ngx_http_send_cached_response(r)); 1490 ngx_http_upstream_cache_send(r, u));
1449 return NGX_OK; 1491 return NGX_OK;
1450 } 1492 }
1451 1493
1452 #endif 1494 #endif
1453 } 1495 }
1555 1597
1556 return NGX_OK; 1598 return NGX_OK;
1557 } 1599 }
1558 1600
1559 1601
1602 static ngx_int_t
1603 ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
1604 {
1605 ngx_str_t *uri, args;
1606 ngx_uint_t i, flags;
1607 ngx_list_part_t *part;
1608 ngx_table_elt_t *h;
1609 ngx_http_upstream_header_t *hh;
1610 ngx_http_upstream_main_conf_t *umcf;
1611
1612 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
1613
1614 if (u->headers_in.x_accel_redirect) {
1615
1616 ngx_http_upstream_finalize_request(r, u, NGX_DECLINED);
1617
1618 part = &u->headers_in.headers.part;
1619 h = part->elts;
1620
1621 for (i = 0; /* void */; i++) {
1622
1623 if (i >= part->nelts) {
1624 if (part->next == NULL) {
1625 break;
1626 }
1627
1628 part = part->next;
1629 h = part->elts;
1630 i = 0;
1631 }
1632
1633 hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
1634 h[i].lowcase_key, h[i].key.len);
1635
1636 if (hh && hh->redirect) {
1637 if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
1638 ngx_http_finalize_request(r,
1639 NGX_HTTP_INTERNAL_SERVER_ERROR);
1640 return NGX_DONE;
1641 }
1642 }
1643 }
1644
1645 uri = &u->headers_in.x_accel_redirect->value;
1646 args.len = 0;
1647 args.data = NULL;
1648 flags = 0;
1649
1650 if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
1651 ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
1652 return NGX_DONE;
1653 }
1654
1655 if (flags & NGX_HTTP_ZERO_IN_URI) {
1656 r->zero_in_uri = 1;
1657 }
1658
1659 if (r->method != NGX_HTTP_HEAD) {
1660 r->method = NGX_HTTP_GET;
1661 }
1662
1663 r->valid_unparsed_uri = 0;
1664
1665 ngx_http_internal_redirect(r, uri, &args);
1666 return NGX_DONE;
1667 }
1668
1669 part = &u->headers_in.headers.part;
1670 h = part->elts;
1671
1672 for (i = 0; /* void */; i++) {
1673
1674 if (i >= part->nelts) {
1675 if (part->next == NULL) {
1676 break;
1677 }
1678
1679 part = part->next;
1680 h = part->elts;
1681 i = 0;
1682 }
1683
1684 if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
1685 h[i].lowcase_key, h[i].key.len))
1686 {
1687 continue;
1688 }
1689
1690 hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
1691 h[i].lowcase_key, h[i].key.len);
1692
1693 if (hh) {
1694 if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
1695 ngx_http_upstream_finalize_request(r, u,
1696 NGX_HTTP_INTERNAL_SERVER_ERROR);
1697 return NGX_DONE;
1698 }
1699
1700 continue;
1701 }
1702
1703 if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK) {
1704 ngx_http_upstream_finalize_request(r, u,
1705 NGX_HTTP_INTERNAL_SERVER_ERROR);
1706 return NGX_DONE;
1707 }
1708 }
1709
1710 if (r->headers_out.server && r->headers_out.server->value.data == NULL) {
1711 r->headers_out.server->hash = 0;
1712 }
1713
1714 if (r->headers_out.date && r->headers_out.date->value.data == NULL) {
1715 r->headers_out.date->hash = 0;
1716 }
1717
1718 r->headers_out.status = u->headers_in.status_n;
1719 r->headers_out.status_line = u->headers_in.status_line;
1720
1721 u->headers_in.content_length_n = r->headers_out.content_length_n;
1722
1723 if (r->headers_out.content_length_n != -1) {
1724 u->length = (size_t) r->headers_out.content_length_n;
1725
1726 } else {
1727 u->length = NGX_MAX_SIZE_T_VALUE;
1728 }
1729
1730 return NGX_OK;
1731 }
1732
1733
1560 static void 1734 static void
1561 ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r, 1735 ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
1562 ngx_http_upstream_t *u) 1736 ngx_http_upstream_t *u)
1563 { 1737 {
1564 size_t size; 1738 size_t size;
1635 int tcp_nodelay; 1809 int tcp_nodelay;
1636 ssize_t n; 1810 ssize_t n;
1637 ngx_int_t rc; 1811 ngx_int_t rc;
1638 ngx_event_pipe_t *p; 1812 ngx_event_pipe_t *p;
1639 ngx_connection_t *c; 1813 ngx_connection_t *c;
1640 ngx_pool_cleanup_t *cl;
1641 ngx_pool_cleanup_file_t *clf;
1642 ngx_http_core_loc_conf_t *clcf; 1814 ngx_http_core_loc_conf_t *clcf;
1643 1815
1644 rc = ngx_http_send_header(r); 1816 rc = ngx_http_send_header(r);
1645 1817
1646 if (rc == NGX_ERROR || rc > NGX_OK || r->post_action || r->header_only) { 1818 if (rc == NGX_ERROR || rc > NGX_OK || r->post_action || r->header_only) {
1649 } 1821 }
1650 1822
1651 u->header_sent = 1; 1823 u->header_sent = 1;
1652 1824
1653 if (r->request_body && r->request_body->temp_file) { 1825 if (r->request_body && r->request_body->temp_file) {
1654 for (cl = r->pool->cleanup; cl; cl = cl->next) { 1826 ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->file.fd);
1655 if (cl->handler == ngx_pool_cleanup_file) { 1827 r->request_body->temp_file->file.fd = NGX_INVALID_FILE;
1656 clf = cl->data;
1657
1658 if (clf->fd == r->request_body->temp_file->file.fd) {
1659 cl->handler(clf);
1660 cl->handler = NULL;
1661 r->request_body->temp_file->file.fd = NGX_INVALID_FILE;
1662 break;
1663 }
1664 }
1665 }
1666 } 1828 }
1667 1829
1668 c = r->connection; 1830 c = r->connection;
1669 1831
1670 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 1832 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1736 return; 1898 return;
1737 } 1899 }
1738 1900
1739 /* TODO: preallocate event_pipe bufs, look "Content-Length" */ 1901 /* TODO: preallocate event_pipe bufs, look "Content-Length" */
1740 1902
1741 #if 0 1903 #if (NGX_HTTP_CACHE)
1742 1904
1743 if (u->cache && u->cache->ctx.file.fd != NGX_INVALID_FILE) { 1905 if (r->cache && r->cache->file.fd != NGX_INVALID_FILE) {
1744 if (ngx_close_file(u->cache->ctx.file.fd) == NGX_FILE_ERROR) { 1906 ngx_pool_run_cleanup_file(r->pool, r->cache->file.fd);
1745 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, 1907 r->cache->file.fd = NGX_INVALID_FILE;
1746 ngx_close_file_n " \"%s\" failed",
1747 u->cache->ctx.file.name.data);
1748 }
1749 } 1908 }
1750 1909
1751 if (u->cacheable) { 1910 if (u->cacheable) {
1752 header = (ngx_http_cache_header_t *) u->buffer->start; 1911 time_t now, valid;
1753 1912
1754 header->expires = u->cache->ctx.expires; 1913 valid = ngx_http_file_cache_valid(u->conf->cache_valid,
1755 header->last_modified = u->cache->ctx.last_modified; 1914 u->headers_in.status_n);
1756 header->date = u->cache->ctx.date; 1915 if (valid) {
1757 header->length = r->headers_out.content_length_n; 1916
1758 u->cache->ctx.length = r->headers_out.content_length_n; 1917 now = ngx_time();
1759 1918
1760 header->key_len = u->cache->ctx.key0.len; 1919 r->cache->valid_sec = now + valid;
1761 ngx_memcpy(&header->key, u->cache->ctx.key0.data, header->key_len); 1920
1762 header->key[header->key_len] = LF; 1921 r->cache->last_modified = r->headers_out.last_modified_time;
1922 r->cache->date = now;
1923 r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
1924
1925 if (r->headers_out.content_length_n != -1) {
1926 r->cache->length = r->cache->body_start
1927 + r->headers_out.content_length_n;
1928 }
1929
1930 ngx_http_file_cache_set_header(r, u->buffer.start);
1931
1932 } else {
1933 u->cacheable = 0;
1934 }
1763 } 1935 }
1764 1936
1765 #endif 1937 #endif
1766 1938
1767 p = u->pipe; 1939 p = u->pipe;
1787 p->temp_file->file.fd = NGX_INVALID_FILE; 1959 p->temp_file->file.fd = NGX_INVALID_FILE;
1788 p->temp_file->file.log = c->log; 1960 p->temp_file->file.log = c->log;
1789 p->temp_file->path = u->conf->temp_path; 1961 p->temp_file->path = u->conf->temp_path;
1790 p->temp_file->pool = r->pool; 1962 p->temp_file->pool = r->pool;
1791 1963
1792 if (u->cacheable || u->store) { 1964 if (p->cacheable) {
1793 p->temp_file->persistent = 1; 1965 p->temp_file->persistent = 1;
1794 1966
1795 } else { 1967 } else {
1796 p->temp_file->log_level = NGX_LOG_WARN; 1968 p->temp_file->log_level = NGX_LOG_WARN;
1797 p->temp_file->warn = "an upstream response is buffered " 1969 p->temp_file->warn = "an upstream response is buffered "
2239 u->pipe->temp_file->file.name.data); 2411 u->pipe->temp_file->file.name.data);
2240 } 2412 }
2241 } 2413 }
2242 } 2414 }
2243 2415
2244 #if (NGX_HTTP_FILE_CACHE) 2416 #if (NGX_HTTP_CACHE)
2245 2417
2246 if (p->upstream_done && u->cacheable) { 2418 if (u->cacheable) {
2247 if (ngx_http_cache_update(r) == NGX_ERROR) { 2419
2248 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock); 2420 if (p->upstream_done) {
2249 ngx_http_upstream_finalize_request(r, u, 0); 2421 ngx_http_file_cache_update(r, u->pipe->temp_file);
2250 return; 2422
2251 } 2423 } else if (p->upstream_eof) {
2252 2424
2253 } else if (p->upstream_eof && u->cacheable) { 2425 /* TODO: check length & update cache */
2254 2426
2255 /* TODO: check length & update cache */ 2427 ngx_http_file_cache_update(r, u->pipe->temp_file);
2256 2428
2257 if (ngx_http_cache_update(r) == NGX_ERROR) { 2429 } else if (p->upstream_error) {
2258 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock); 2430 ngx_http_file_cache_free(r, u->pipe->temp_file);
2259 ngx_http_upstream_finalize_request(r, u, 0);
2260 return;
2261 } 2431 }
2262 } 2432 }
2263 2433
2264 #endif 2434 #endif
2265 2435
2436 2606
2437 if (u->peer.tries == 0 || !(u->conf->next_upstream & ft_type)) { 2607 if (u->peer.tries == 0 || !(u->conf->next_upstream & ft_type)) {
2438 2608
2439 #if (NGX_HTTP_CACHE) 2609 #if (NGX_HTTP_CACHE)
2440 2610
2441 if (u->stale && (u->conf->use_stale & ft_type)) { 2611 if (u->stale_cache && (u->conf->cache_use_stale & ft_type)) {
2612
2442 ngx_http_upstream_finalize_request(r, u, 2613 ngx_http_upstream_finalize_request(r, u,
2443 ngx_http_send_cached_response(r)); 2614 ngx_http_upstream_cache_send(r, u));
2444 return; 2615 return;
2445 } 2616 }
2446
2447 #endif 2617 #endif
2448 2618
2449 ngx_http_upstream_finalize_request(r, u, status); 2619 ngx_http_upstream_finalize_request(r, u, status);
2450 return; 2620 return;
2451 } 2621 }
2555 ngx_close_connection(u->peer.connection); 2725 ngx_close_connection(u->peer.connection);
2556 } 2726 }
2557 2727
2558 u->peer.connection = NULL; 2728 u->peer.connection = NULL;
2559 2729
2560 if (u->header_sent && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
2561 {
2562 rc = 0;
2563 }
2564
2565 if (u->pipe && u->pipe->temp_file) { 2730 if (u->pipe && u->pipe->temp_file) {
2566 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 2731 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2567 "http upstream temp fd: %d", 2732 "http upstream temp fd: %d",
2568 u->pipe->temp_file->file.fd); 2733 u->pipe->temp_file->file.fd);
2569 } 2734 }
2570 2735
2571 #if 0 2736 #if (NGX_HTTP_CACHE)
2572 if (u->cache) { 2737
2738 if (r->cache) {
2739 time_t valid;
2740
2573 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 2741 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2574 "http upstream cache fd: %d", 2742 "http upstream cache fd: %d",
2575 u->cache->ctx.file.fd); 2743 r->cache->file.fd);
2576 } 2744
2745 if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT) {
2746
2747 valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc);
2748
2749 if (valid) {
2750 r->cache->valid_sec = ngx_time() + valid;
2751 r->cache->error = rc;
2752 }
2753 }
2754
2755 ngx_http_file_cache_free(r, u->pipe->temp_file);
2756 }
2757
2577 #endif 2758 #endif
2759
2760 if (u->header_sent && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
2761 {
2762 rc = 0;
2763 }
2578 2764
2579 if (rc == NGX_DECLINED) { 2765 if (rc == NGX_DECLINED) {
2580 return; 2766 return;
2581 } 2767 }
2582 2768
2825 return NGX_OK; 3011 return NGX_OK;
2826 } 3012 }
2827 3013
2828 3014
2829 static ngx_int_t 3015 static ngx_int_t
3016 ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
3017 ngx_uint_t offset)
3018 {
3019 ngx_table_elt_t *ho;
3020
3021 ho = ngx_list_push(&r->headers_out.headers);
3022 if (ho == NULL) {
3023 return NGX_ERROR;
3024 }
3025
3026 *ho = *h;
3027
3028 #if (NGX_HTTP_CACHE)
3029
3030 if (r->cached) {
3031 r->headers_out.last_modified = ho;
3032 r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data,
3033 h->value.len);
3034 }
3035
3036 #endif
3037
3038 return NGX_OK;
3039 }
3040
3041
3042 static ngx_int_t
2830 ngx_http_upstream_rewrite_location(ngx_http_request_t *r, ngx_table_elt_t *h, 3043 ngx_http_upstream_rewrite_location(ngx_http_request_t *r, ngx_table_elt_t *h,
2831 ngx_uint_t offset) 3044 ngx_uint_t offset)
2832 { 3045 {
2833 ngx_int_t rc; 3046 ngx_int_t rc;
2834 ngx_table_elt_t *ho; 3047 ngx_table_elt_t *ho;
2909 3122
2910 return rc; 3123 return rc;
2911 } 3124 }
2912 3125
2913 r->headers_out.refresh = ho; 3126 r->headers_out.refresh = ho;
3127
3128 return NGX_OK;
3129 }
3130
3131
3132 static ngx_int_t
3133 ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
3134 ngx_table_elt_t *h, ngx_uint_t offset)
3135 {
3136 ngx_table_elt_t *ho;
3137
3138 #if (NGX_HTTP_CACHE)
3139
3140 if (r->cached) {
3141 r->allow_ranges = 1;
3142 return NGX_OK;
3143
3144 }
3145
3146 #endif
3147
3148 ho = ngx_list_push(&r->headers_out.headers);
3149 if (ho == NULL) {
3150 return NGX_ERROR;
3151 }
3152
3153 *ho = *h;
2914 3154
2915 return NGX_OK; 3155 return NGX_OK;
2916 } 3156 }
2917 3157
2918 3158