comparison src/http/ngx_http_upstream.c @ 6905:9a9e13686869

Cache: support for stale-while-revalidate and stale-if-error. Previously, there was no way to enable the proxy_cache_use_stale behavior by reading the backend response. Now, stale-while-revalidate and stale-if-error Cache-Control extensions (RFC 5861) are supported. They specify, how long a stale response can be used when a cache entry is being updated, or in case of an error.
author Roman Arutyunyan <arut@nginx.com>
date Thu, 22 Dec 2016 14:25:34 +0300
parents d2b2ff157da5
children 1aeaae6e9446
comparison
equal deleted inserted replaced
6904:5e2423bce883 6905:9a9e13686869
869 869
870 switch (rc) { 870 switch (rc) {
871 871
872 case NGX_HTTP_CACHE_UPDATING: 872 case NGX_HTTP_CACHE_UPDATING:
873 873
874 if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) { 874 if ((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
875 || c->stale_updating)
876 {
875 u->cache_status = rc; 877 u->cache_status = rc;
876 rc = NGX_OK; 878 rc = NGX_OK;
877 879
878 } else { 880 } else {
879 rc = NGX_HTTP_CACHE_STALE; 881 rc = NGX_HTTP_CACHE_STALE;
892 return NGX_OK; 894 return NGX_OK;
893 895
894 case NGX_HTTP_CACHE_STALE: 896 case NGX_HTTP_CACHE_STALE:
895 897
896 c->valid_sec = 0; 898 c->valid_sec = 0;
899 c->updating_sec = 0;
900 c->error_sec = 0;
901
897 u->buffer.start = NULL; 902 u->buffer.start = NULL;
898 u->cache_status = NGX_HTTP_CACHE_EXPIRED; 903 u->cache_status = NGX_HTTP_CACHE_EXPIRED;
899 904
900 break; 905 break;
901 906
2338 } 2343 }
2339 2344
2340 #if (NGX_HTTP_CACHE) 2345 #if (NGX_HTTP_CACHE)
2341 2346
2342 if (u->cache_status == NGX_HTTP_CACHE_EXPIRED 2347 if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
2343 && (u->conf->cache_use_stale & un->mask)) 2348 && ((u->conf->cache_use_stale & un->mask) || r->cache->stale_error))
2344 { 2349 {
2345 ngx_int_t rc; 2350 ngx_int_t rc;
2346 2351
2347 rc = u->reinit_request(r); 2352 rc = u->reinit_request(r);
2348 2353
2362 2367
2363 if (status == NGX_HTTP_NOT_MODIFIED 2368 if (status == NGX_HTTP_NOT_MODIFIED
2364 && u->cache_status == NGX_HTTP_CACHE_EXPIRED 2369 && u->cache_status == NGX_HTTP_CACHE_EXPIRED
2365 && u->conf->cache_revalidate) 2370 && u->conf->cache_revalidate)
2366 { 2371 {
2367 time_t now, valid; 2372 time_t now, valid, updating, error;
2368 ngx_int_t rc; 2373 ngx_int_t rc;
2369 2374
2370 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 2375 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2371 "http upstream not modified"); 2376 "http upstream not modified");
2372 2377
2373 now = ngx_time(); 2378 now = ngx_time();
2379
2374 valid = r->cache->valid_sec; 2380 valid = r->cache->valid_sec;
2381 updating = r->cache->updating_sec;
2382 error = r->cache->error_sec;
2375 2383
2376 rc = u->reinit_request(r); 2384 rc = u->reinit_request(r);
2377 2385
2378 if (rc != NGX_OK) { 2386 if (rc != NGX_OK) {
2379 ngx_http_upstream_finalize_request(r, u, rc); 2387 ngx_http_upstream_finalize_request(r, u, rc);
2383 u->cache_status = NGX_HTTP_CACHE_REVALIDATED; 2391 u->cache_status = NGX_HTTP_CACHE_REVALIDATED;
2384 rc = ngx_http_upstream_cache_send(r, u); 2392 rc = ngx_http_upstream_cache_send(r, u);
2385 2393
2386 if (valid == 0) { 2394 if (valid == 0) {
2387 valid = r->cache->valid_sec; 2395 valid = r->cache->valid_sec;
2396 updating = r->cache->updating_sec;
2397 error = r->cache->error_sec;
2388 } 2398 }
2389 2399
2390 if (valid == 0) { 2400 if (valid == 0) {
2391 valid = ngx_http_file_cache_valid(u->conf->cache_valid, 2401 valid = ngx_http_file_cache_valid(u->conf->cache_valid,
2392 u->headers_in.status_n); 2402 u->headers_in.status_n);
2395 } 2405 }
2396 } 2406 }
2397 2407
2398 if (valid) { 2408 if (valid) {
2399 r->cache->valid_sec = valid; 2409 r->cache->valid_sec = valid;
2410 r->cache->updating_sec = updating;
2411 r->cache->error_sec = error;
2412
2400 r->cache->date = now; 2413 r->cache->date = now;
2401 2414
2402 ngx_http_file_cache_update_header(r); 2415 ngx_http_file_cache_update_header(r);
2403 } 2416 }
2404 2417
4130 || (timeout && ngx_current_msec - u->peer.start_time >= timeout)) 4143 || (timeout && ngx_current_msec - u->peer.start_time >= timeout))
4131 { 4144 {
4132 #if (NGX_HTTP_CACHE) 4145 #if (NGX_HTTP_CACHE)
4133 4146
4134 if (u->cache_status == NGX_HTTP_CACHE_EXPIRED 4147 if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
4135 && (u->conf->cache_use_stale & ft_type)) 4148 && ((u->conf->cache_use_stale & ft_type) || r->cache->stale_error))
4136 { 4149 {
4137 ngx_int_t rc; 4150 ngx_int_t rc;
4138 4151
4139 rc = u->reinit_request(r); 4152 rc = u->reinit_request(r);
4140 4153
4505 if (p == NULL) { 4518 if (p == NULL) {
4506 p = ngx_strlcasestrn(start, last, (u_char *) "max-age=", 8 - 1); 4519 p = ngx_strlcasestrn(start, last, (u_char *) "max-age=", 8 - 1);
4507 offset = 8; 4520 offset = 8;
4508 } 4521 }
4509 4522
4510 if (p == NULL) { 4523 if (p) {
4511 return NGX_OK; 4524 n = 0;
4512 } 4525
4513 4526 for (p += offset; p < last; p++) {
4514 n = 0; 4527 if (*p == ',' || *p == ';' || *p == ' ') {
4515 4528 break;
4516 for (p += offset; p < last; p++) { 4529 }
4517 if (*p == ',' || *p == ';' || *p == ' ') { 4530
4518 break; 4531 if (*p >= '0' && *p <= '9') {
4519 } 4532 n = n * 10 + *p - '0';
4520 4533 continue;
4521 if (*p >= '0' && *p <= '9') { 4534 }
4522 n = n * 10 + *p - '0'; 4535
4523 continue; 4536 u->cacheable = 0;
4524 } 4537 return NGX_OK;
4525 4538 }
4526 u->cacheable = 0; 4539
4527 return NGX_OK; 4540 if (n == 0) {
4528 } 4541 u->cacheable = 0;
4529 4542 return NGX_OK;
4530 if (n == 0) { 4543 }
4531 u->cacheable = 0; 4544
4532 return NGX_OK; 4545 r->cache->valid_sec = ngx_time() + n;
4533 } 4546 }
4534 4547
4535 r->cache->valid_sec = ngx_time() + n; 4548 p = ngx_strlcasestrn(start, last, (u_char *) "stale-while-revalidate=",
4549 23 - 1);
4550
4551 if (p) {
4552 n = 0;
4553
4554 for (p += 23; p < last; p++) {
4555 if (*p == ',' || *p == ';' || *p == ' ') {
4556 break;
4557 }
4558
4559 if (*p >= '0' && *p <= '9') {
4560 n = n * 10 + *p - '0';
4561 continue;
4562 }
4563
4564 u->cacheable = 0;
4565 return NGX_OK;
4566 }
4567
4568 r->cache->updating_sec = n;
4569 r->cache->error_sec = n;
4570 }
4571
4572 p = ngx_strlcasestrn(start, last, (u_char *) "stale-if-error=", 15 - 1);
4573
4574 if (p) {
4575 n = 0;
4576
4577 for (p += 15; p < last; p++) {
4578 if (*p == ',' || *p == ';' || *p == ' ') {
4579 break;
4580 }
4581
4582 if (*p >= '0' && *p <= '9') {
4583 n = n * 10 + *p - '0';
4584 continue;
4585 }
4586
4587 u->cacheable = 0;
4588 return NGX_OK;
4589 }
4590
4591 r->cache->error_sec = n;
4592 }
4536 } 4593 }
4537 #endif 4594 #endif
4538 4595
4539 return NGX_OK; 4596 return NGX_OK;
4540 } 4597 }