diff options
Diffstat (limited to 'src/http/ngx_http_file_cache.c')
-rw-r--r-- | src/http/ngx_http_file_cache.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index 2eebc3068..e1b16e9c6 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -29,6 +29,10 @@ static ngx_http_file_cache_node_t * ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key); static void ngx_http_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); +static void ngx_http_file_cache_vary(ngx_http_request_t *r, u_char *vary, + size_t len, u_char *hash); +static void ngx_http_file_cache_vary_header(ngx_http_request_t *r, + ngx_md5_t *md5, ngx_str_t *name); static void ngx_http_file_cache_cleanup(void *data); static time_t ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache); static time_t ngx_http_file_cache_expire(ngx_http_file_cache_t *cache); @@ -519,6 +523,23 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) return NGX_DECLINED; } + if (h->vary_len > NGX_HTTP_CACHE_VARY_LEN) { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, + "cache file \"%s\" has incorrect vary length", + c->file.name.data); + return NGX_DECLINED; + } + + if (h->vary_len) { + ngx_http_file_cache_vary(r, h->vary, h->vary_len, c->variant); + + if (ngx_memcmp(c->variant, h->variant, NGX_HTTP_CACHE_KEY_LEN) != 0) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http file cache vary mismatch"); + return NGX_DECLINED; + } + } + c->buf->last += n; c->valid_sec = h->valid_sec; @@ -870,6 +891,94 @@ ngx_http_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp, } +static void +ngx_http_file_cache_vary(ngx_http_request_t *r, u_char *vary, size_t len, + u_char *hash) +{ + u_char *p, *last; + ngx_str_t name; + ngx_md5_t md5; + u_char buf[NGX_HTTP_CACHE_VARY_LEN]; + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http file cache vary: \"%*s\"", len, vary); + + ngx_md5_init(&md5); + + ngx_strlow(buf, vary, len); + + p = buf; + last = buf + len; + + while (p < last) { + + while (p < last && (*p == ' ' || *p == ',')) { p++; } + + name.data = p; + + while (p < last && *p != ',' && *p != ' ') { p++; } + + name.len = p - name.data; + + if (name.len == 0) { + break; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http file cache vary: %V", &name); + + ngx_md5_update(&md5, name.data, name.len); + ngx_md5_update(&md5, (u_char *) ":", sizeof(":") - 1); + + ngx_http_file_cache_vary_header(r, &md5, &name); + + ngx_md5_update(&md5, (u_char *) CRLF, sizeof(CRLF) - 1); + } + + ngx_md5_final(hash, &md5); +} + + +static void +ngx_http_file_cache_vary_header(ngx_http_request_t *r, ngx_md5_t *md5, + ngx_str_t *name) +{ + ngx_uint_t i; + ngx_list_part_t *part; + ngx_table_elt_t *header; + + part = &r->headers_in.headers.part; + header = part->elts; + + for (i = 0; /* void */ ; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + header = part->elts; + i = 0; + } + + if (header[i].hash == 0) { + continue; + } + + if (header[i].key.len != name->len) { + continue; + } + + if (ngx_strncasecmp(header[i].key.data, name->data, name->len) != 0) { + continue; + } + + ngx_md5_update(md5, header[i].value.data, header[i].value.len); + } +} + + void ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf) { @@ -901,6 +1010,19 @@ ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf) ngx_memcpy(h->etag, c->etag.data, c->etag.len); } + if (c->vary.len) { + if (c->vary.len > NGX_HTTP_CACHE_VARY_LEN) { + /* should not happen */ + c->vary.len = NGX_HTTP_CACHE_VARY_LEN; + } + + h->vary_len = (u_char) c->vary.len; + ngx_memcpy(h->vary, c->vary.data, c->vary.len); + + ngx_http_file_cache_vary(r, c->vary.data, c->vary.len, c->variant); + ngx_memcpy(h->variant, c->variant, NGX_HTTP_CACHE_KEY_LEN); + } + p = buf + sizeof(ngx_http_file_cache_header_t); p = ngx_cpymem(p, ngx_http_file_cache_key, sizeof(ngx_http_file_cache_key)); @@ -1093,6 +1215,19 @@ ngx_http_file_cache_update_header(ngx_http_request_t *r) ngx_memcpy(h.etag, c->etag.data, c->etag.len); } + if (c->vary.len) { + if (c->vary.len > NGX_HTTP_CACHE_VARY_LEN) { + /* should not happen */ + c->vary.len = NGX_HTTP_CACHE_VARY_LEN; + } + + h.vary_len = (u_char) c->vary.len; + ngx_memcpy(h.vary, c->vary.data, c->vary.len); + + ngx_http_file_cache_vary(r, c->vary.data, c->vary.len, c->variant); + ngx_memcpy(h.variant, c->variant, NGX_HTTP_CACHE_KEY_LEN); + } + (void) ngx_write_file(&file, (u_char *) &h, sizeof(ngx_http_file_cache_header_t), 0); |