Hi all,
please find attached a new more general approch to prevent cookies from being stored in the cache. As proposed by Justin I replaced my original CacheStoreCookies directive with the more general CacheIgnoreHeaders directive. So far I only tested it for myself. If someone could test / have a look at it, it would be nice and appreciated. Meanwhile I try to get additional testers and will report about the results later.
Regards
Rüdiger
diff -Nrup httpd-2.0.52.orig/docs/manual/mod/mod_cache.xml httpd-2.0.52/docs/manual/mod/mod_cache.xml --- httpd-2.0.52.orig/docs/manual/mod/mod_cache.xml 2004-04-17 20:43:37.000000000 +0200 +++ httpd-2.0.52/docs/manual/mod/mod_cache.xml 2004-10-14 23:11:39.000000000 +0200 @@ -332,4 +332,57 @@ will complete caching the file even if t </usage> </directivesynopsis> +<directivesynopsis> +<name>CacheIgnoreHeaders</name> +<description>Do not store the given HTTP header(s) in the cache. +</description> +<syntax>CacheIgnoreHeaders <var>header-string</var> [<var>header-string</var>] ...</syntax> +<default>CacheIgnoreHeaders None</default> +<contextlist><context>server config</context><context>virtual host</context> +</contextlist> + +<usage> + <p>According to RFC 2616 only hop-by-hop HTTP headers are not stored in + the cache. The following HTTP headers are hop-by-hop headers and thus + do not get stored in the cache in <em>any</em> case regardless of the + setting of <directive>CacheIgnoreHeaders</directive>:</p> + + <ul> + <li><code>Connection</code></li> + <li><code>Keep-Alive</code></li> + <li><code>Proxy-Authenticate</code></li> + <li><code>Proxy-Authorization</code></li> + <li><code>TE</code></li> + <li><code>Trailers</code></li> + <li><code>Transfer-Encoding</code></li> + <li><code>Upgrade</code></li> + </ul> + + <p><directive>CacheIgnoreHeaders</directive> allows to add additional HTTP + headers that should not to be stored in the cache. For example it makes + sense in some cases to prevent cookies from being stored in the cache.</p> + + <p><directive>CacheIgnoreHeaders</directive> takes a space separated list + of HTTP headers that should not be stored in the cache. If all none + hop-by-hop headers should be stored in the cache (RFC 2616 compliant + behaviour), <directive>CacheIgnoreHeaders</directive> can be set to + <code>None</code>.</p> + + <example><title>Example 1</title> + CacheIgnoreHeaders Set-Cookie + </example> + + <example><title>Example 2</title> + CacheIgnoreHeaders None + </example> + + <note type="warning"><title>Warning:</title> + If headers like <code>Expires</code> that are needed for the cache + management are not stored due to a + <directive>CacheIgnoreHeaders</directive> setting, the behaviour of + mod_cache is undefined. + </note> +</usage> +</directivesynopsis> + </modulesynopsis> diff -Nrup httpd-2.0.52.orig/modules/experimental/cache_util.c httpd-2.0.52/modules/experimental/cache_util.c --- httpd-2.0.52.orig/modules/experimental/cache_util.c 2004-08-26 18:59:44.000000000 +0200 +++ httpd-2.0.52/modules/experimental/cache_util.c 2004-10-14 20:28:48.000000000 +0200 @@ -21,6 +21,8 @@ /* -------------------------------------------------------------- */ +extern module cache_module; + /* return true if the request is conditional */ CACHE_DECLARE(int) ap_cache_request_is_conditional(request_rec *r) { @@ -517,8 +519,13 @@ CACHE_DECLARE(char *)generate_name(apr_p * headers table that are allowed to be stored in a cache. */ CACHE_DECLARE(apr_table_t *)ap_cache_cacheable_hdrs_out(apr_pool_t *pool, - apr_table_t *t) + apr_table_t *t, + server_rec *s) { + cache_server_conf *conf; + char **header; + int i; + /* Make a copy of the headers, and remove from * the copy any hop-by-hop headers, as defined in Section * 13.5.1 of RFC 2616 @@ -533,5 +540,14 @@ CACHE_DECLARE(apr_table_t *)ap_cache_cac apr_table_unset(headers_out, "Trailers"); apr_table_unset(headers_out, "Transfer-Encoding"); apr_table_unset(headers_out, "Upgrade"); + conf = (cache_server_conf *)ap_get_module_config(s->module_config, + &cache_module); + /* Remove the user defined headers set with CacheIgnoreHeaders. + * This may break RFC 2616 compliance on behalf of the users wish. + */ + header = (char **)conf->ignore_headers->elts; + for (i = 0; i < conf->ignore_headers->nelts; i++) { + apr_table_unset(headers_out, header[i]); + } return headers_out; } diff -Nrup httpd-2.0.52.orig/modules/experimental/mod_cache.c httpd-2.0.52/modules/experimental/mod_cache.c --- httpd-2.0.52.orig/modules/experimental/mod_cache.c 2004-08-26 18:59:44.000000000 +0200 +++ httpd-2.0.52/modules/experimental/mod_cache.c 2004-10-14 20:28:48.000000000 +0200 @@ -749,6 +749,9 @@ static void * create_cache_config(apr_po ps->no_last_mod_ignore = 0; ps->ignorecachecontrol = 0; ps->ignorecachecontrol_set = 0 ; + /* array of headers that should not be stored in cache */ + ps->ignore_headers = apr_array_make(p, 10, sizeof(char *)); + ps->ignore_headers_set = CACHE_IGNORE_HEADERS_UNSET; return ps; } @@ -785,6 +788,10 @@ static void * merge_cache_config(apr_poo (overrides->ignorecachecontrol_set == 0) ? base->ignorecachecontrol : overrides->ignorecachecontrol; + ps->ignore_headers = + (overrides->ignore_headers_set == CACHE_IGNORE_HEADERS_UNSET) + ? base->ignore_headers + : overrides->ignore_headers; return ps; } static const char *set_cache_ignore_no_last_mod(cmd_parms *parms, void *dummy, @@ -814,6 +821,33 @@ static const char *set_cache_ignore_cach return NULL; } +static const char *add_ignore_header(cmd_parms *parms, void *dummy, + const char *header) +{ + cache_server_conf *conf; + char **new; + + conf = + (cache_server_conf *)ap_get_module_config(parms->server->module_config, + &cache_module); + if (!strncasecmp(header, "None", 4)) { + /* if header None is listed clear array */ + conf->ignore_headers->nelts = 0; + } + else { + if ((conf->ignore_headers_set == CACHE_IGNORE_HEADERS_UNSET) || + (conf->ignore_headers->nelts)) { + /* Only add header if no "None" has been found in header list + * so far. + */ + new = (char **)apr_array_push(conf->ignore_headers); + (*new) = header; + } + } + conf->ignore_headers_set = CACHE_IGNORE_HEADERS_SET; + return NULL; +} + static const char *add_cache_enable(cmd_parms *parms, void *dummy, const char *type, const char *url) @@ -946,6 +980,8 @@ static const command_rec cache_cmds[] = NULL, RSRC_CONF, "Ignore requests from the client for uncached content"), + AP_INIT_ITERATE("CacheIgnoreHeaders", add_ignore_header, NULL, RSRC_CONF, + "A space separated list of headers that should not be stored by the cache"), AP_INIT_TAKE1("CacheLastModifiedFactor", set_cache_factor, NULL, RSRC_CONF, "The factor used to estimate Expires date from " "LastModified date"), diff -Nrup httpd-2.0.52.orig/modules/experimental/mod_cache.h httpd-2.0.52/modules/experimental/mod_cache.h --- httpd-2.0.52.orig/modules/experimental/mod_cache.h 2004-08-26 20:35:13.000000000 +0200 +++ httpd-2.0.52/modules/experimental/mod_cache.h 2004-10-14 20:28:48.000000000 +0200 @@ -133,6 +133,17 @@ typedef struct { /** ignore client's requests for uncached responses */ int ignorecachecontrol; int ignorecachecontrol_set; + /** store the headers that should not be stored in the cache */ + apr_array_header_t *ignore_headers; + /* flag if CacheIgnoreHeader has been set + * FIXME: defined as 2 state variable as a starting point + * for a later migration of complete / complete_set, no_last_mod_ignore + * / no_last_mod_ignore_set, ignorecachecontrol / ignorecachecontrol_set + * to three state variables. + */ + #define CACHE_IGNORE_HEADERS_SET 1 + #define CACHE_IGNORE_HEADERS_UNSET 0 + unsigned int ignore_headers_set : 1; } cache_server_conf; /* cache info information */ @@ -249,7 +260,7 @@ CACHE_DECLARE(const char *)ap_cache_toks /* Create a new table consisting of those elements from a request_rec's * headers_out that are allowed to be stored in a cache */ -CACHE_DECLARE(apr_table_t *)ap_cache_cacheable_hdrs_out(apr_pool_t *pool, apr_table_t *t); +CACHE_DECLARE(apr_table_t *)ap_cache_cacheable_hdrs_out(apr_pool_t *pool, apr_table_t *t, server_rec *s); /** * cache_storage.c diff -Nrup httpd-2.0.52.orig/modules/experimental/mod_disk_cache.c httpd-2.0.52/modules/experimental/mod_disk_cache.c --- httpd-2.0.52.orig/modules/experimental/mod_disk_cache.c 2004-08-26 18:59:44.000000000 +0200 +++ httpd-2.0.52/modules/experimental/mod_disk_cache.c 2004-10-14 20:28:48.000000000 +0200 @@ -581,7 +581,8 @@ static apr_status_t store_headers(cache_ if (r->headers_out) { apr_table_t *headers_out; - headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out); + headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out, + r->server); rv = store_table(hfd, headers_out); if (rv != APR_SUCCESS) { diff -Nrup httpd-2.0.52.orig/modules/experimental/mod_mem_cache.c httpd-2.0.52/modules/experimental/mod_mem_cache.c --- httpd-2.0.52.orig/modules/experimental/mod_mem_cache.c 2004-09-17 17:03:08.000000000 +0200 +++ httpd-2.0.52/modules/experimental/mod_mem_cache.c 2004-10-14 20:28:48.000000000 +0200 @@ -742,13 +742,15 @@ static apr_status_t store_headers(cache_ /* Precompute how much storage we need to hold the headers */ rc = serialize_table(&mobj->header_out, &mobj->num_header_out, - ap_cache_cacheable_hdrs_out(r->pool, r->headers_out)); + ap_cache_cacheable_hdrs_out(r->pool, r->headers_out, + r->server)); if (rc != APR_SUCCESS) { return rc; } rc = serialize_table(&mobj->err_header_out, &mobj->num_err_header_out, - ap_cache_cacheable_hdrs_out(r->pool, r->err_headers_out)); + ap_cache_cacheable_hdrs_out(r->pool, r->err_headers_out, + r->server)); if (rc != APR_SUCCESS) { return rc; }