diff options
Diffstat (limited to 'modules/cache/mod_cache.c')
-rw-r--r-- | modules/cache/mod_cache.c | 89 |
1 files changed, 50 insertions, 39 deletions
diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c index 20360553..cd839ed7 100644 --- a/modules/cache/mod_cache.c +++ b/modules/cache/mod_cache.c @@ -36,6 +36,22 @@ static ap_filter_rec_t *cache_out_subreq_filter_handle; static ap_filter_rec_t *cache_remove_url_filter_handle; static ap_filter_rec_t *cache_invalidate_filter_handle; +/** + * Entity headers' names + */ +static const char *MOD_CACHE_ENTITY_HEADERS[] = { + "Allow", + "Content-Encoding", + "Content-Language", + "Content-Length", + "Content-Location", + "Content-MD5", + "Content-Range", + "Content-Type", + "Last-Modified", + NULL +}; + /* * CACHE handler * ------------- @@ -697,7 +713,7 @@ static int cache_save_store(ap_filter_t *f, apr_bucket_brigade *in, rv = cache->provider->store_body(cache->handle, f->r, in, cache->out); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, f->r, APLOGNO(00765) - "cache: Cache provider's store_body failed!"); + "cache: Cache provider's store_body failed for URI %s", f->r->uri); ap_remove_output_filter(f); /* give someone else the chance to cache the file */ @@ -756,17 +772,16 @@ static int cache_save_store(ap_filter_t *f, apr_bucket_brigade *in, /** * Sanity check for 304 Not Modified responses, as per RFC2616 Section 10.3.5. */ -static const char *cache_header_cmp(apr_pool_t *pool, apr_table_t *left, +static int cache_header_cmp(apr_pool_t *pool, apr_table_t *left, apr_table_t *right, const char *key) { const char *h1, *h2; if ((h1 = cache_table_getm(pool, left, key)) && (h2 = cache_table_getm(pool, right, key)) && (strcmp(h1, h2))) { - return apr_pstrcat(pool, "contradiction: 304 Not Modified, but ", key, - " modified", NULL); + return 1; } - return NULL; + return 0; } /* @@ -802,7 +817,7 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) apr_time_t exp, date, lastmod, now; apr_off_t size = -1; cache_info *info = NULL; - const char *reason; + const char *reason, **eh; apr_pool_t *p; apr_bucket *e; apr_table_t *headers; @@ -1111,29 +1126,22 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) else if (r->status == HTTP_NOT_MODIFIED && cache->stale_handle) { apr_table_t *left = cache->stale_handle->resp_hdrs; apr_table_t *right = r->headers_out; + const char *ehs = NULL; /* and lastly, contradiction checks for revalidated responses * as per RFC2616 Section 10.3.5 */ - if (((reason = cache_header_cmp(r->pool, left, right, "Allow"))) - || ((reason = cache_header_cmp(r->pool, left, right, - "Content-Encoding"))) - || ((reason = cache_header_cmp(r->pool, left, right, - "Content-Language"))) - || ((reason = cache_header_cmp(r->pool, left, right, - "Content-Length"))) - || ((reason = cache_header_cmp(r->pool, left, right, - "Content-Location"))) - || ((reason = cache_header_cmp(r->pool, left, right, - "Content-MD5"))) - || ((reason = cache_header_cmp(r->pool, left, right, - "Content-Range"))) - || ((reason = cache_header_cmp(r->pool, left, right, - "Content-Type"))) - || ((reason = cache_header_cmp(r->pool, left, right, "ETag"))) - || ((reason = cache_header_cmp(r->pool, left, right, - "Last-Modified")))) { - /* contradiction: 304 Not Modified, but entity header modified */ + if (cache_header_cmp(r->pool, left, right, "ETag")) { + ehs = "ETag"; + } + for (eh = MOD_CACHE_ENTITY_HEADERS; *eh; ++eh) { + if (cache_header_cmp(r->pool, left, right, *eh)) { + ehs = (ehs) ? apr_pstrcat(r->pool, ehs, ", ", *eh, NULL) : *eh; + } + } + if (ehs) { + reason = apr_pstrcat(r->pool, "contradiction: 304 Not Modified; " + "but ", ehs, " modified", NULL); } } @@ -1148,14 +1156,9 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) * inconsistencies between cached entity-bodies and updated headers. */ if (r->status == HTTP_NOT_MODIFIED) { - apr_table_unset(r->headers_out, "Allow"); - apr_table_unset(r->headers_out, "Content-Encoding"); - apr_table_unset(r->headers_out, "Content-Language"); - apr_table_unset(r->headers_out, "Content-Length"); - apr_table_unset(r->headers_out, "Content-MD5"); - apr_table_unset(r->headers_out, "Content-Range"); - apr_table_unset(r->headers_out, "Content-Type"); - apr_table_unset(r->headers_out, "Last-Modified"); + for (eh = MOD_CACHE_ENTITY_HEADERS; *eh; ++eh) { + apr_table_unset(r->headers_out, *eh); + } } /* Hold the phone. Some servers might allow us to cache a 2xx, but @@ -1198,7 +1201,7 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) apr_table_unset(r->headers_in, "If-Range"); apr_table_unset(r->headers_in, "If-Unmodified-Since"); - ap_internal_redirect(r->uri, r); + ap_internal_redirect(r->unparsed_uri, r); return APR_SUCCESS; } @@ -1439,10 +1442,12 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) * the cached headers. * * However, before doing that, we need to first merge in - * err_headers_out and we also need to strip any hop-by-hop - * headers that might have snuck in. + * err_headers_out (note that store_headers() below already selects + * the cacheable only headers using ap_cache_cacheable_headers_out(), + * here we want to keep the original headers in r->headers_out and + * forward all of them to the client, including non-cacheable ones). */ - r->headers_out = ap_cache_cacheable_headers_out(r); + r->headers_out = cache_merge_headers_out(r); /* Merge in our cached headers. However, keep any updated values. */ /* take output, overlay on top of cached */ @@ -1492,6 +1497,13 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) if (status != OK) { r->status = status; + /* Strip the entity headers merged from the cached headers before + * updating the entry (see cache_accept_headers() above). + */ + for (eh = MOD_CACHE_ENTITY_HEADERS; *eh; ++eh) { + apr_table_unset(r->headers_out, *eh); + } + bkt = apr_bucket_flush_create(bb->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, bkt); } @@ -2071,8 +2083,7 @@ static const char *set_cache_quick_handler(cmd_parms *parms, void *dummy, cache_server_conf *conf; conf = - (cache_server_conf *)ap_get_module_config(parms->server->module_config -, + (cache_server_conf *)ap_get_module_config(parms->server->module_config, &cache_module); conf->quick = flag; conf->quick_set = 1; |