Mercurial > hg > nginx-vendor-0-7
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 |