comparison src/http/ngx_http_upstream.c @ 539:5f4de8cf0d9d

Merge with current.
author Maxim Dounin <mdounin@mdounin.ru>
date Tue, 15 Sep 2009 03:43:40 +0400
parents 0161f3197817
children 4c5d2c627a6c
comparison
equal deleted inserted replaced
522:40fd8d7b82f9 539:5f4de8cf0d9d
16 ngx_http_upstream_t *u); 16 ngx_http_upstream_t *u);
17 static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r, 17 static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,
18 ngx_http_variable_value_t *v, uintptr_t data); 18 ngx_http_variable_value_t *v, uintptr_t data);
19 #endif 19 #endif
20 20
21 static void ngx_http_upstream_init_request(ngx_http_request_t *r);
21 static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx); 22 static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx);
22 static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r); 23 static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r);
23 static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r); 24 static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r);
24 static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, 25 static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
25 ngx_event_t *ev); 26 ngx_event_t *ev);
159 { ngx_string("Last-Modified"), 160 { ngx_string("Last-Modified"),
160 ngx_http_upstream_process_header_line, 161 ngx_http_upstream_process_header_line,
161 offsetof(ngx_http_upstream_headers_in_t, last_modified), 162 offsetof(ngx_http_upstream_headers_in_t, last_modified),
162 ngx_http_upstream_copy_last_modified, 0, 0 }, 163 ngx_http_upstream_copy_last_modified, 0, 0 },
163 164
165 { ngx_string("ETag"),
166 ngx_http_upstream_process_header_line,
167 offsetof(ngx_http_upstream_headers_in_t, etag),
168 ngx_http_upstream_copy_header_line,
169 offsetof(ngx_http_headers_out_t, etag), 0 },
170
164 { ngx_string("Server"), 171 { ngx_string("Server"),
165 ngx_http_upstream_process_header_line, 172 ngx_http_upstream_process_header_line,
166 offsetof(ngx_http_upstream_headers_in_t, server), 173 offsetof(ngx_http_upstream_headers_in_t, server),
167 ngx_http_upstream_copy_header_line, 174 ngx_http_upstream_copy_header_line,
168 offsetof(ngx_http_headers_out_t, server), 0 }, 175 offsetof(ngx_http_headers_out_t, server), 0 },
354 ngx_http_upstream_t *u; 361 ngx_http_upstream_t *u;
355 362
356 u = r->upstream; 363 u = r->upstream;
357 364
358 if (u && u->cleanup) { 365 if (u && u->cleanup) {
366 r->main->count++;
359 ngx_http_upstream_cleanup(r); 367 ngx_http_upstream_cleanup(r);
360 *u->cleanup = NULL; 368 *u->cleanup = NULL;
361 } 369 }
362 370
363 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); 371 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
371 u->peer.log_error = NGX_ERROR_ERR; 379 u->peer.log_error = NGX_ERROR_ERR;
372 #if (NGX_THREADS) 380 #if (NGX_THREADS)
373 u->peer.lock = &r->connection->lock; 381 u->peer.lock = &r->connection->lock;
374 #endif 382 #endif
375 383
384 #if (NGX_HTTP_CACHE)
385 r->cache = NULL;
386 #endif
387
376 return NGX_OK; 388 return NGX_OK;
377 } 389 }
378 390
379 391
380 void 392 void
381 ngx_http_upstream_init(ngx_http_request_t *r) 393 ngx_http_upstream_init(ngx_http_request_t *r)
382 { 394 {
395 ngx_connection_t *c;
396
397 c = r->connection;
398
399 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
400 "http init upstream, client timer: %d", c->read->timer_set);
401
402 if (c->read->timer_set) {
403 ngx_del_timer(c->read);
404 }
405
406 if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
407
408 if (!c->write->active) {
409 if (ngx_add_event(c->write, NGX_WRITE_EVENT, NGX_CLEAR_EVENT)
410 == NGX_ERROR)
411 {
412 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
413 return;
414 }
415 }
416 }
417
418 ngx_http_upstream_init_request(r);
419 }
420
421
422 static void
423 ngx_http_upstream_init_request(ngx_http_request_t *r)
424 {
383 ngx_str_t *host; 425 ngx_str_t *host;
384 ngx_uint_t i; 426 ngx_uint_t i;
385 ngx_connection_t *c;
386 ngx_resolver_ctx_t *ctx, temp; 427 ngx_resolver_ctx_t *ctx, temp;
387 ngx_http_cleanup_t *cln; 428 ngx_http_cleanup_t *cln;
388 ngx_http_upstream_t *u; 429 ngx_http_upstream_t *u;
389 ngx_http_core_loc_conf_t *clcf; 430 ngx_http_core_loc_conf_t *clcf;
390 ngx_http_upstream_srv_conf_t *uscf, **uscfp; 431 ngx_http_upstream_srv_conf_t *uscf, **uscfp;
391 ngx_http_upstream_main_conf_t *umcf; 432 ngx_http_upstream_main_conf_t *umcf;
392 433
393 c = r->connection; 434 if (r->aio) {
394 435 return;
395 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
396 "http init upstream, client timer: %d", c->read->timer_set);
397
398 if (c->read->timer_set) {
399 ngx_del_timer(c->read);
400 } 436 }
401 437
402 u = r->upstream; 438 u = r->upstream;
439
440 #if (NGX_HTTP_CACHE)
441
442 if (u->conf->cache) {
443 ngx_int_t rc;
444
445 rc = ngx_http_upstream_cache(r, u);
446
447 if (rc == NGX_BUSY) {
448 r->write_event_handler = ngx_http_upstream_init_request;
449 return;
450 }
451
452 r->write_event_handler = ngx_http_request_empty_handler;
453
454 if (rc == NGX_DONE) {
455 return;
456 }
457
458 if (rc != NGX_DECLINED) {
459 ngx_http_finalize_request(r, rc);
460 return;
461 }
462 }
463
464 #endif
403 465
404 u->store = (u->conf->store || u->conf->store_lengths); 466 u->store = (u->conf->store || u->conf->store_lengths);
405 467
406 if (!u->store && !r->post_action && !u->conf->ignore_client_abort) { 468 if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
407 r->read_event_handler = ngx_http_upstream_rd_check_broken_connection; 469 r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
408 r->write_event_handler = ngx_http_upstream_wr_check_broken_connection; 470 r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
409 } 471 }
410 472
411 if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
412
413 if (!c->write->active) {
414 if (ngx_add_event(c->write, NGX_WRITE_EVENT, NGX_CLEAR_EVENT)
415 == NGX_ERROR)
416 {
417 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
418 return;
419 }
420 }
421 }
422
423 if (r->request_body) { 473 if (r->request_body) {
424 u->request_bufs = r->request_body->bufs; 474 u->request_bufs = r->request_body->bufs;
425 } 475 }
426 476
427 #if (NGX_HTTP_CACHE)
428
429 if (u->conf->cache) {
430 ngx_int_t rc;
431
432 rc = ngx_http_upstream_cache(r, u);
433
434 if (rc == NGX_DONE) {
435 return;
436 }
437
438 if (rc != NGX_DECLINED) {
439 ngx_http_finalize_request(r, rc);
440 return;
441 }
442 }
443
444 #endif
445
446 if (u->create_request(r) != NGX_OK) { 477 if (u->create_request(r) != NGX_OK) {
447 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 478 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
448 return; 479 return;
449 } 480 }
450 481
451 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 482 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
452 483
484 u->output.alignment = clcf->directio_alignment;
453 u->output.pool = r->pool; 485 u->output.pool = r->pool;
454 u->output.bufs.num = 1; 486 u->output.bufs.num = 1;
455 u->output.bufs.size = clcf->client_body_buffer_size; 487 u->output.bufs.size = clcf->client_body_buffer_size;
456 u->output.output_filter = ngx_chain_writer; 488 u->output.output_filter = ngx_chain_writer;
457 u->output.filter_ctx = &u->writer; 489 u->output.filter_ctx = &u->writer;
535 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 567 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
536 return; 568 return;
537 } 569 }
538 570
539 if (ctx == NGX_NO_RESOLVER) { 571 if (ctx == NGX_NO_RESOLVER) {
540 ngx_log_error(NGX_LOG_ERR, c->log, 0, 572 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
541 "no resolver defined to resolve %V", host); 573 "no resolver defined to resolve %V", host);
542 574
543 ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY); 575 ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY);
544 return; 576 return;
545 } 577 }
578 ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u) 610 ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
579 { 611 {
580 ngx_int_t rc; 612 ngx_int_t rc;
581 ngx_http_cache_t *c; 613 ngx_http_cache_t *c;
582 614
583 if (!(r->method & u->conf->cache_methods)) { 615 c = r->cache;
584 return NGX_DECLINED; 616
585 }
586
587 if (r->method & NGX_HTTP_HEAD) {
588 u->method = ngx_http_core_get_method;
589 }
590
591 c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t));
592 if (c == NULL) { 617 if (c == NULL) {
593 return NGX_ERROR; 618
594 } 619 if (!(r->method & u->conf->cache_methods)) {
595 620 return NGX_DECLINED;
596 if (ngx_array_init(&c->keys, r->pool, 4, sizeof(ngx_str_t)) != NGX_OK) { 621 }
597 return NGX_ERROR; 622
598 } 623 if (r->method & NGX_HTTP_HEAD) {
599 624 u->method = ngx_http_core_get_method;
600 r->cache = c; 625 }
601 c->file.log = r->connection->log; 626
602 627 c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t));
603 if (u->create_key(r) != NGX_OK) { 628 if (c == NULL) {
604 return NGX_ERROR; 629 return NGX_ERROR;
605 } 630 }
606 631
607 /* TODO: add keys */ 632 if (ngx_array_init(&c->keys, r->pool, 4, sizeof(ngx_str_t)) != NGX_OK) {
608 633 return NGX_ERROR;
609 ngx_http_file_cache_create_key(r); 634 }
610 635
611 u->cacheable = 1; 636 r->cache = c;
612 637 c->file.log = r->connection->log;
613 c->min_uses = u->conf->cache_min_uses; 638
614 c->body_start = u->conf->buffer_size; 639 if (u->create_key(r) != NGX_OK) {
615 c->file_cache = u->conf->cache->data; 640 return NGX_ERROR;
616 641 }
617 u->cache_status = NGX_HTTP_CACHE_MISS; 642
643 /* TODO: add keys */
644
645 ngx_http_file_cache_create_key(r);
646
647 u->cacheable = 1;
648
649 c->min_uses = u->conf->cache_min_uses;
650 c->body_start = u->conf->buffer_size;
651 c->file_cache = u->conf->cache->data;
652
653 u->cache_status = NGX_HTTP_CACHE_MISS;
654 }
618 655
619 rc = ngx_http_file_cache_open(r); 656 rc = ngx_http_file_cache_open(r);
620 657
621 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 658 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
622 "http upstream cache: %i", rc); 659 "http upstream cache: %i", rc);
649 return rc; 686 return rc;
650 } 687 }
651 688
652 break; 689 break;
653 690
654 case NGX_ERROR:
655
656 return NGX_ERROR;
657
658 case NGX_HTTP_CACHE_STALE: 691 case NGX_HTTP_CACHE_STALE:
659 692
660 c->valid_sec = 0; 693 c->valid_sec = 0;
661 u->buffer.start = NULL; 694 u->buffer.start = NULL;
662 u->cache_status = NGX_HTTP_CACHE_EXPIRED; 695 u->cache_status = NGX_HTTP_CACHE_EXPIRED;
673 u->buffer.last = u->buffer.pos; 706 u->buffer.last = u->buffer.pos;
674 } 707 }
675 708
676 break; 709 break;
677 710
711 case NGX_HTTP_CACHE_SCARCE:
712
713 u->cacheable = 0;
714
715 break;
716
678 case NGX_AGAIN: 717 case NGX_AGAIN:
679 718
680 u->cacheable = 0; 719 return NGX_BUSY;
681 720
682 break; 721 case NGX_ERROR:
722
723 return NGX_ERROR;
683 724
684 default: 725 default:
685 726
686 /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */ 727 /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */
687 728
1772 } 1813 }
1773 1814
1774 r->valid_unparsed_uri = 0; 1815 r->valid_unparsed_uri = 0;
1775 1816
1776 ngx_http_internal_redirect(r, uri, &args); 1817 ngx_http_internal_redirect(r, uri, &args);
1818 ngx_http_finalize_request(r, NGX_DONE);
1777 return NGX_DONE; 1819 return NGX_DONE;
1778 } 1820 }
1779 1821
1780 part = &u->headers_in.headers.part; 1822 part = &u->headers_in.headers.part;
1781 h = part->elts; 1823 h = part->elts;
2070 } 2112 }
2071 } 2113 }
2072 2114
2073 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 2115 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
2074 "http cacheable: %d", u->cacheable); 2116 "http cacheable: %d", u->cacheable);
2117
2118 if (u->cacheable == 0 && r->cache) {
2119 ngx_http_file_cache_free(r, u->pipe->temp_file);
2120 }
2075 2121
2076 #endif 2122 #endif
2077 2123
2078 p = u->pipe; 2124 p = u->pipe;
2079 2125
2252 if (do_write) { 2298 if (do_write) {
2253 2299
2254 if (u->out_bufs || u->busy_bufs) { 2300 if (u->out_bufs || u->busy_bufs) {
2255 rc = ngx_http_output_filter(r, u->out_bufs); 2301 rc = ngx_http_output_filter(r, u->out_bufs);
2256 2302
2257 if (downstream->destroyed) {
2258 return;
2259 }
2260
2261 if (rc == NGX_ERROR) { 2303 if (rc == NGX_ERROR) {
2262 ngx_http_upstream_finalize_request(r, u, 0); 2304 ngx_http_upstream_finalize_request(r, u, 0);
2263 return; 2305 return;
2264 } 2306 }
2265 2307
2428 2470
2429 return; 2471 return;
2430 } 2472 }
2431 2473
2432 if (ngx_event_pipe(p, wev->write) == NGX_ABORT) { 2474 if (ngx_event_pipe(p, wev->write) == NGX_ABORT) {
2433
2434 if (c->destroyed) {
2435 return;
2436 }
2437
2438 ngx_http_upstream_finalize_request(r, u, 0); 2475 ngx_http_upstream_finalize_request(r, u, 0);
2439 return; 2476 return;
2440 } 2477 }
2441 2478
2442 } else { 2479 } else {
2458 2495
2459 return; 2496 return;
2460 } 2497 }
2461 2498
2462 if (ngx_event_pipe(p, 1) == NGX_ABORT) { 2499 if (ngx_event_pipe(p, 1) == NGX_ABORT) {
2463
2464 if (c->destroyed) {
2465 return;
2466 }
2467
2468 ngx_http_upstream_finalize_request(r, u, 0); 2500 ngx_http_upstream_finalize_request(r, u, 0);
2469 return; 2501 return;
2470 } 2502 }
2471 } 2503 }
2472 2504
2490 if (c->read->timedout) { 2522 if (c->read->timedout) {
2491 u->pipe->upstream_error = 1; 2523 u->pipe->upstream_error = 1;
2492 ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); 2524 ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
2493 2525
2494 } else { 2526 } else {
2495 c = r->connection;
2496
2497 if (ngx_event_pipe(u->pipe, 0) == NGX_ABORT) { 2527 if (ngx_event_pipe(u->pipe, 0) == NGX_ABORT) {
2498
2499 if (c->destroyed) {
2500 return;
2501 }
2502
2503 ngx_http_upstream_finalize_request(r, u, 0); 2528 ngx_http_upstream_finalize_request(r, u, 0);
2504 return; 2529 return;
2505 } 2530 }
2506 } 2531 }
2507 2532
2633 ext.access = u->conf->store_access; 2658 ext.access = u->conf->store_access;
2634 ext.path_access = u->conf->store_access; 2659 ext.path_access = u->conf->store_access;
2635 ext.time = -1; 2660 ext.time = -1;
2636 ext.create_path = 1; 2661 ext.create_path = 1;
2637 ext.delete_file = 1; 2662 ext.delete_file = 1;
2638 ext.log_rename_error = 1;
2639 ext.log = r->connection->log; 2663 ext.log = r->connection->log;
2640 2664
2641 if (u->headers_in.last_modified) { 2665 if (u->headers_in.last_modified) {
2642 2666
2643 lm = ngx_http_parse_time(u->headers_in.last_modified->value.data, 2667 lm = ngx_http_parse_time(u->headers_in.last_modified->value.data,
2660 { 2684 {
2661 return; 2685 return;
2662 } 2686 }
2663 } 2687 }
2664 2688
2689 path.len--;
2690
2665 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 2691 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2666 "upstream stores \"%s\" to \"%s\"", 2692 "upstream stores \"%s\" to \"%s\"",
2667 tf->file.name.data, path.data); 2693 tf->file.name.data, path.data);
2668 2694
2669 (void) ngx_ext_rename_file(&tf->file.name, &path, &ext); 2695 (void) ngx_ext_rename_file(&tf->file.name, &path, &ext);
2881 u->pipe->temp_file->file.fd); 2907 u->pipe->temp_file->file.fd);
2882 } 2908 }
2883 2909
2884 #if (NGX_HTTP_CACHE) 2910 #if (NGX_HTTP_CACHE)
2885 2911
2886 if (u->cacheable) { 2912 if (u->cacheable && r->cache) {
2887 time_t valid; 2913 time_t valid;
2888 2914
2889 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 2915 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2890 "http upstream cache fd: %d", 2916 "http upstream cache fd: %d",
2891 r->cache->file.fd); 2917 r->cache->file.fd);