From: Graham Leggett Date: Wed, 8 May 2013 14:06:48 +0000 (+0000) Subject: Ensure that Warning headers are correctly handled as per RFC2616. X-Git-Tag: 2.5.0-alpha~5483 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5c93801e6506fefe30ea19b50fddfa77f62b8035;p=apache Ensure that Warning headers are correctly handled as per RFC2616. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1480283 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/cache/cache_storage.c b/modules/cache/cache_storage.c index 42b1a55f08..38080fdbcc 100644 --- a/modules/cache/cache_storage.c +++ b/modules/cache/cache_storage.c @@ -113,9 +113,30 @@ int cache_create_entity(cache_request_rec *cache, request_rec *r, return DECLINED; } +static int filter_header_do(void *v, const char *key, const char *val) +{ + if ((*key == 'W' || *key == 'w') && !strcasecmp(key, "Warning") + && *val == '1') { + /* any stored Warning headers with warn-code 1xx (see section + * 14.46) MUST be deleted from the cache entry and the forwarded + * response. + */ + } + else { + apr_table_addn(v, key, val); + } + return 1; +} static int remove_header_do(void *v, const char *key, const char *val) { - apr_table_unset(v, key); + if ((*key == 'W' || *key == 'w') && !strcasecmp(key, "Warning")) { + /* any stored Warning headers with warn-code 2xx MUST be retained + * in the cache entry and the forwarded response. + */ + } + else { + apr_table_unset(v, key); + } return 1; } static int add_header_do(void *v, const char *key, const char *val) @@ -130,20 +151,25 @@ static int add_header_do(void *v, const char *key, const char *val) * * To complicate this, a header may be duplicated in either table. Should a * header exist in the top table, all matching headers will be removed from - * the bottom table before the headers are combined. + * the bottom table before the headers are combined. The Warning headers are + * handled specially. Warnings are added rather than being replaced, while + * in the case of revalidation 1xx Warnings are stripped. * * The Content-Type and Last-Modified headers are then re-parsed and inserted * into the request. */ void cache_accept_headers(cache_handle_t *h, request_rec *r, apr_table_t *top, - apr_table_t *bottom) + apr_table_t *bottom, int revalidation) { const char *v; - if (r->headers_out != bottom) { + if (revalidation) { + r->headers_out = apr_table_make(r->pool, 10); + apr_table_do(filter_header_do, r->headers_out, bottom, NULL); + } + else if (r->headers_out != bottom) { r->headers_out = apr_table_copy(r->pool, bottom); } - apr_table_do(remove_header_do, r->headers_out, top, NULL); apr_table_do(add_header_do, r->headers_out, top, NULL); @@ -372,7 +398,7 @@ int cache_select(cache_request_rec *cache, request_rec *r) } /* Okay, this response looks okay. Merge in our stuff and go. */ - cache_accept_headers(h, r, h->resp_hdrs, r->headers_out); + cache_accept_headers(h, r, h->resp_hdrs, r->headers_out, 0); cache->handle = h; return OK; diff --git a/modules/cache/cache_storage.h b/modules/cache/cache_storage.h index f0f32f2315..83f2946f5a 100644 --- a/modules/cache/cache_storage.h +++ b/modules/cache/cache_storage.h @@ -63,9 +63,10 @@ apr_status_t cache_generate_key_default(request_rec *r, apr_pool_t* p, * @param r request_rec * @param top headers to be applied * @param bottom headers to be overwritten + * @param revalidation true if revalidation is taking place */ void cache_accept_headers(cache_handle_t *h, request_rec *r, apr_table_t *top, - apr_table_t *bottom); + apr_table_t *bottom, int revalidation); #ifdef __cplusplus } diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c index e183b3a257..5451d8113c 100644 --- a/modules/cache/mod_cache.c +++ b/modules/cache/mod_cache.c @@ -1190,7 +1190,7 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) /* Merge in our cached headers. However, keep any updated values. */ /* take output, overlay on top of cached */ cache_accept_headers(cache->handle, r, r->headers_out, - cache->handle->resp_hdrs); + cache->handle->resp_hdrs, 1); status = ap_meets_conditions(r); if (status != OK) { @@ -1469,7 +1469,7 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) /* Merge in our cached headers. However, keep any updated values. */ /* take output, overlay on top of cached */ cache_accept_headers(cache->handle, r, r->headers_out, - cache->handle->resp_hdrs); + cache->handle->resp_hdrs, 1); } /* Write away header information to cache. It is possible that we are