summaryrefslogtreecommitdiffhomepage
path: root/src/http/ngx_http_upstream.c
diff options
context:
space:
mode:
authorRoman Arutyunyan <arut@nginx.com>2016-12-22 14:25:34 +0300
committerRoman Arutyunyan <arut@nginx.com>2016-12-22 14:25:34 +0300
commitda2b2cf1e039630cec84e8b67d99c4d578361b0d (patch)
treeabe94ca9f27fa0322e0fda2ee4922e08e91bcdb9 /src/http/ngx_http_upstream.c
parent42f3dd2b843157ea0982b165b69c5dad84095811 (diff)
downloadnginx-da2b2cf1e039630cec84e8b67d99c4d578361b0d.tar.gz
nginx-da2b2cf1e039630cec84e8b67d99c4d578361b0d.tar.bz2
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.
Diffstat (limited to 'src/http/ngx_http_upstream.c')
-rw-r--r--src/http/ngx_http_upstream.c97
1 files changed, 77 insertions, 20 deletions
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index c59519416..d33ddd66e 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -871,7 +871,9 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
case NGX_HTTP_CACHE_UPDATING:
- if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) {
+ if ((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
+ || c->stale_updating)
+ {
u->cache_status = rc;
rc = NGX_OK;
@@ -894,6 +896,9 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
case NGX_HTTP_CACHE_STALE:
c->valid_sec = 0;
+ c->updating_sec = 0;
+ c->error_sec = 0;
+
u->buffer.start = NULL;
u->cache_status = NGX_HTTP_CACHE_EXPIRED;
@@ -2340,7 +2345,7 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
#if (NGX_HTTP_CACHE)
if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
- && (u->conf->cache_use_stale & un->mask))
+ && ((u->conf->cache_use_stale & un->mask) || r->cache->stale_error))
{
ngx_int_t rc;
@@ -2364,14 +2369,17 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
&& u->cache_status == NGX_HTTP_CACHE_EXPIRED
&& u->conf->cache_revalidate)
{
- time_t now, valid;
+ time_t now, valid, updating, error;
ngx_int_t rc;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http upstream not modified");
now = ngx_time();
+
valid = r->cache->valid_sec;
+ updating = r->cache->updating_sec;
+ error = r->cache->error_sec;
rc = u->reinit_request(r);
@@ -2385,6 +2393,8 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
if (valid == 0) {
valid = r->cache->valid_sec;
+ updating = r->cache->updating_sec;
+ error = r->cache->error_sec;
}
if (valid == 0) {
@@ -2397,6 +2407,9 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
if (valid) {
r->cache->valid_sec = valid;
+ r->cache->updating_sec = updating;
+ r->cache->error_sec = error;
+
r->cache->date = now;
ngx_http_file_cache_update_header(r);
@@ -4132,7 +4145,7 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
#if (NGX_HTTP_CACHE)
if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
- && (u->conf->cache_use_stale & ft_type))
+ && ((u->conf->cache_use_stale & ft_type) || r->cache->stale_error))
{
ngx_int_t rc;
@@ -4507,32 +4520,76 @@ ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
offset = 8;
}
- if (p == NULL) {
- return NGX_OK;
- }
+ if (p) {
+ n = 0;
- n = 0;
+ for (p += offset; p < last; p++) {
+ if (*p == ',' || *p == ';' || *p == ' ') {
+ break;
+ }
- for (p += offset; p < last; p++) {
- if (*p == ',' || *p == ';' || *p == ' ') {
- break;
+ if (*p >= '0' && *p <= '9') {
+ n = n * 10 + *p - '0';
+ continue;
+ }
+
+ u->cacheable = 0;
+ return NGX_OK;
}
- if (*p >= '0' && *p <= '9') {
- n = n * 10 + *p - '0';
- continue;
+ if (n == 0) {
+ u->cacheable = 0;
+ return NGX_OK;
}
- u->cacheable = 0;
- return NGX_OK;
+ r->cache->valid_sec = ngx_time() + n;
}
- if (n == 0) {
- u->cacheable = 0;
- return NGX_OK;
+ p = ngx_strlcasestrn(start, last, (u_char *) "stale-while-revalidate=",
+ 23 - 1);
+
+ if (p) {
+ n = 0;
+
+ for (p += 23; p < last; p++) {
+ if (*p == ',' || *p == ';' || *p == ' ') {
+ break;
+ }
+
+ if (*p >= '0' && *p <= '9') {
+ n = n * 10 + *p - '0';
+ continue;
+ }
+
+ u->cacheable = 0;
+ return NGX_OK;
+ }
+
+ r->cache->updating_sec = n;
+ r->cache->error_sec = n;
}
- r->cache->valid_sec = ngx_time() + n;
+ p = ngx_strlcasestrn(start, last, (u_char *) "stale-if-error=", 15 - 1);
+
+ if (p) {
+ n = 0;
+
+ for (p += 15; p < last; p++) {
+ if (*p == ',' || *p == ';' || *p == ' ') {
+ break;
+ }
+
+ if (*p >= '0' && *p <= '9') {
+ n = n * 10 + *p - '0';
+ continue;
+ }
+
+ u->cacheable = 0;
+ return NGX_OK;
+ }
+
+ r->cache->error_sec = n;
+ }
}
#endif