aboutsummaryrefslogtreecommitdiff
path: root/src/http/ngx_http_file_cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/http/ngx_http_file_cache.c')
-rw-r--r--src/http/ngx_http_file_cache.c135
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);