In fact this patch is probably better since it does not change h->resp_hdrs before calling cache_accept_headers() which uses them.
Regars, Yann. Index: modules/cache/cache_util.c =================================================================== --- modules/cache/cache_util.c (revision 1461557) +++ modules/cache/cache_util.c (working copy) @@ -542,13 +542,10 @@ } /* These come from the cached entity. */ - if (h->cache_obj->info.control.no_cache - || h->cache_obj->info.control.no_cache_header - || h->cache_obj->info.control.private_header) { + if (h->cache_obj->info.control.no_cache) { /* - * The cached entity contained Cache-Control: no-cache, or a - * no-cache with a header present, or a private with a header - * present, so treat as stale causing revalidation. + * The cached entity contained Cache-Control: no-cache, + * so treat as stale causing revalidation. */ return 0; } @@ -1069,9 +1066,7 @@ /* ...then try slowest cases */ else if (!strncasecmp(token, "no-cache", 8)) { if (token[8] == '=') { - if (apr_table_get(headers, token + 9)) { - cc->no_cache_header = 1; - } + cc->no_cache_header = 1; } else if (!token[8]) { cc->no_cache = 1; @@ -1146,9 +1141,7 @@ } else if (!strncasecmp(token, "private", 7)) { if (token[7] == '=') { - if (apr_table_get(headers, token + 8)) { - cc->private_header = 1; - } + cc->private_header = 1; } else if (!token[7]) { cc->private = 1; Index: modules/cache/mod_cache.c =================================================================== --- modules/cache/mod_cache.c (revision 1461557) +++ modules/cache/mod_cache.c (working copy) @@ -714,6 +714,65 @@ } /* + * Same as ap_cacheable_headers_out(), but also strips the headers + * specified by the Cache-Control private= or no-cache= directives. + */ +static int cc_field_doo_doo(void *t, const char *key, + const char *val) +{ + if (val) { + apr_table_addn(t, key, val); + return 0; + } + return 1; +} +static apr_table_t *cache_cacheable_headers_cc(request_rec *r, + const cache_control_t *cc) +{ + apr_table_t *headers_out = ap_cache_cacheable_headers_out(r); + if (cc && (cc->no_cache_header || cc->private_header)) { + char *token; + const char *cc_out = apr_table_get(headers_out, "Cache-Control"); + while (cc_out && (token = ap_get_list_item(r->pool, &cc_out))) { + apr_size_t len = strlen(token); + + /* ap_get_list_item() strips the spurious whitespaces and + * lowercases anything (but the quoted-strings) */ + if (len > 9 && strncmp(token, "no-cache=", 9) == 0) { + token += 9; + len -= 9; + } + else if (len > 8 && strncmp(token, "private=", 8) == 0) { + token += 8; + len -= 8; + } + else { + continue; + } + + /* RFC2616 14.9: quoted list of field-names */ + if (len > 2 && token[0] == '"' && token[--len] == '"') { + /* strip the header(s) from the cacheable headers out, + * but preserve the ones from the current response by + * adding them to the err_headers_out */ + const char *tok, *header; + (++token)[--len] = '\0'; + tok = token; + do { + if ((header = ap_cache_tokstr(r->pool, tok, &tok)) && + !apr_table_do(cc_field_doo_doo, r->err_headers_out, + headers_out, header, NULL)) { + apr_table_unset(r->headers_out, header); + apr_table_unset(headers_out, header); + } + } while (tok); + } + } + } + return headers_out; +} + +/* * CACHE_SAVE filter * --------------- * @@ -746,6 +805,7 @@ apr_time_t exp, date, lastmod, now; apr_off_t size = -1; cache_info *info = NULL; + apr_table_t *cc_headers; char *reason; apr_pool_t *p; apr_bucket *e; @@ -1075,7 +1135,7 @@ * err_headers_out and we also need to strip any hop-by-hop * headers that might have snuck in. */ - r->headers_out = ap_cache_cacheable_headers_out(r); + r->headers_out = cache_cacheable_headers_cc(r, &control); /* Merge in our cached headers. However, keep any updated values. */ cache_accept_headers(cache->handle, r, 1); @@ -1332,6 +1392,8 @@ } info->expire = exp; + cc_headers = cache_cacheable_headers_cc(r, &control); + /* We found a stale entry which wasn't really stale. */ if (cache->stale_handle) { /* Load in the saved status and clear the status line. */ @@ -1347,12 +1409,15 @@ * err_headers_out and we also need to strip any hop-by-hop * headers that might have snuck in. */ - r->headers_out = ap_cache_cacheable_headers_out(r); + r->headers_out = cc_headers; /* Merge in our cached headers. However, keep any updated values. */ cache_accept_headers(cache->handle, r, 1); } + cache->handle->req_hdrs = ap_cache_cacheable_headers_in(r); + cache->handle->resp_hdrs = cc_headers; + /* Write away header information to cache. It is possible that we are * trying to update headers for an entity which has already been cached. * Index: modules/cache/mod_cache_disk.c =================================================================== --- modules/cache/mod_cache_disk.c (revision 1461557) +++ modules/cache/mod_cache_disk.c (working copy) @@ -933,11 +933,11 @@ memcpy(&h->cache_obj->info, info, sizeof(cache_info)); if (r->headers_out) { - dobj->headers_out = ap_cache_cacheable_headers_out(r); + dobj->headers_out = h->resp_hdrs; } if (r->headers_in) { - dobj->headers_in = ap_cache_cacheable_headers_in(r); + dobj->headers_in = h->req_hdrs; } return APR_SUCCESS; Index: modules/cache/mod_cache_socache.c =================================================================== --- modules/cache/mod_cache_socache.c (revision 1461557) +++ modules/cache/mod_cache_socache.c (working copy) @@ -791,11 +791,11 @@ memcpy(&h->cache_obj->info, info, sizeof(cache_info)); if (r->headers_out) { - sobj->headers_out = ap_cache_cacheable_headers_out(r); + sobj->headers_out = h->resp_hdrs; } if (r->headers_in) { - sobj->headers_in = ap_cache_cacheable_headers_in(r); + sobj->headers_in = h->req_hdrs; } sobj->expire