Mercurial > hg > nginx
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 } |