From: Justin Erenkrantz Date: Wed, 2 Feb 2005 07:10:20 +0000 (+0000) Subject: Add CacheStorePrivate, CacheStoreNoStore, and clarify CacheIgnoreCacheControl. X-Git-Tag: 2.1.3~83 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4743f301f2d8691af4140bae88adb337492e09ca;p=apache Add CacheStorePrivate, CacheStoreNoStore, and clarify CacheIgnoreCacheControl. * docs/manual/mod/mod_cache.xml: Update documentation for CacheIgnoreCacheControl and add documentation for two new directives. * modules/cache/mod_cache.c (cache_url_handler): Honor 'Cache-Control: no-cache' request header. (cache_save_filter): Only honor no-store or private when their respective directives are Off (which is the default). rest of file: add in standard configuration syntax stuff... * modules/cache/mod_cache.h: Minor formatting tweak and add new fields. Suggested by: Pier Fumagalli git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@149492 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 43f98c1ad6..11bc0f556e 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,9 @@ Changes with Apache 2.1.3 [Remove entries to the current 2.0 section below, when backported] + *) mod_cache: Add CacheStorePrivate and CacheStoreNoStore directive. + [Justin Erenkrantz] + *) Remove compiled-in upper limit on LimitRequestFieldSize. [Bill Stoddard] diff --git a/docs/manual/mod/mod_cache.xml b/docs/manual/mod/mod_cache.xml index 46fcbc0d5a..78001a6ee2 100644 --- a/docs/manual/mod/mod_cache.xml +++ b/docs/manual/mod/mod_cache.xml @@ -235,24 +235,33 @@ header. CacheIgnoreCacheControl -Ignore the fact that the client requested the content not be -cached. +Ignore request to not serve cached content to client CacheIgnoreCacheControl On|Off CacheIgnoreCacheControl Off server configvirtual host -

Ordinarily, documents with no-cache or no-store header values will not be stored in the cache. - The CacheIgnoreCacheControl directive allows this behavior to be overridden. - CacheIgnoreCacheControl On tells the server to attempt to cache the document - even if it contains no-cache or no-store header values. Documents requiring authorization will - never be cached.

+

Ordinarily, requests containing a Cache-Control: no-cache or + Pragma: no-cache header value will not be served from the cache. The + CacheIgnoreCacheControl directive allows this + behavior to be overridden. CacheIgnoreCacheControl + On tells the server to attempt to serve the resource from the cache even + if the request contains no-cache header values. Resources requiring + authorization will never be cached.

CacheIgnoreCacheControl On + + Warning: + This directive will allow serving from the cache even if the client has + requested that the document not be served from the cache. This might + result in stale content being served. +
+CacheStorePrivate +CacheStoreNoStore
@@ -343,4 +352,66 @@ LastModified date. + +CacheStorePrivate +Attempt to cache responses that the server has marked as private +CacheStorePrivate On|Off +CacheStorePrivate Off +server configvirtual host + + + +

Ordinarily, responses with Cache-Control: private header values will not + be stored in the cache. The CacheStorePrivate + directive allows this behavior to be overridden. + CacheStorePrivate On + tells the server to attempt to cache the resource even if it contains + private header values. Resources requiring authorization will + never be cached.

+ + + CacheStorePrivate On + + + Warning: + This directive will allow caching even if the upstream server has + requested that the resource not be cached. This directive is only + ideal for a 'private' cache. + +
+CacheIgnoreCacheControl +CacheStoreNoStore +
+ + +CacheStoreNoStore +Attempt to cache requests or responses that have been marked as no-store. +CacheStoreNoStore On|Off +CacheStoreNoStore Off +server configvirtual host + + + +

Ordinarily, requests or responses with Cache-Control: no-store header + values will not be stored in the cache. The + CacheStoreNoCache directive allows this + behavior to be overridden. CacheStoreNoCache On + tells the server to attempt to cache the resource even if it contains + no-store header values. Resources requiring authorization will + never be cached.

+ + + CacheStoreNoStore On + + + Warning: + As described in RFC 2616, the no-store directive is intended to + "prevent the inadvertent release or retention of sensitive information + (for example, on backup tapes)." Enabling this option could store + sensitive information in the cache. You are hereby warned. + +
+CacheIgnoreCacheControl +CacheStorePrivate +
diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c index 335ab81585..d0959636e6 100644 --- a/modules/cache/mod_cache.c +++ b/modules/cache/mod_cache.c @@ -47,7 +47,7 @@ static ap_filter_rec_t *cache_out_filter_handle; static int cache_url_handler(request_rec *r, int lookup) { apr_status_t rv; - const char *pragma, *auth; + const char *auth; apr_uri_t uri; char *url; char *path; @@ -93,21 +93,23 @@ static int cache_url_handler(request_rec *r, int lookup) */ /* find certain cache controlling headers */ - pragma = apr_table_get(r->headers_in, "Pragma"); auth = apr_table_get(r->headers_in, "Authorization"); /* first things first - does the request allow us to return * cached information at all? If not, just decline the request. * * Note that there is a big difference between not being allowed - * to cache a request (no-store) and not being allowed to return + * to cache a response (no-store) and not being allowed to return * a cached request without revalidation (max-age=0). * - * Caching is forbidden under the following circumstances: + * Serving from a cache is forbidden under the following circumstances: * - * - RFC2616 14.9.2 Cache-Control: no-store + * - RFC2616 14.9.1 Cache-Control: no-cache * - Pragma: no-cache * - Any requests requiring authorization. + * + * Updating a cache is forbidden under the following circumstances: + * - RFC2616 14.9.2 Cache-Control: no-store */ if (conf->ignorecachecontrol == 1 && auth == NULL) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, @@ -115,8 +117,14 @@ static int cache_url_handler(request_rec *r, int lookup) "%s, but we know better and are ignoring it", url); } else { - if (ap_cache_liststr(NULL, pragma, "no-cache", NULL) || - auth != NULL) { + const char *pragma, *cc_in; + + pragma = apr_table_get(r->headers_in, "Pragma"); + cc_in = apr_table_get(r->headers_in, "Cache-Control"); + + if (auth != NULL || + ap_cache_liststr(NULL, pragma, "no-cache", NULL) || + ap_cache_liststr(NULL, cc_in, "no-cache", NULL)) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "cache: no-cache or authorization forbids caching " "of %s", url); @@ -263,10 +271,16 @@ static int cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) char *reason; apr_pool_t *p; - /* check first whether running this filter has any point or not */ - /* If the user has Cache-Control: no-store from RFC 2616, don't store! */ + conf = (cache_server_conf *) ap_get_module_config(r->server->module_config, + &cache_module); + + /* If the request has Cache-Control: no-store from RFC 2616, don't store + * unless CacheStoreNoStore is active. + */ cc_in = apr_table_get(r->headers_in, "Cache-Control"); - if (r->no_cache || ap_cache_liststr(NULL, cc_in, "no-store", NULL)) { + if (r->no_cache || + (!conf->store_nostore && + ap_cache_liststr(NULL, cc_in, "no-store", NULL))) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, in); } @@ -349,7 +363,6 @@ static int cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) lastmod = APR_DATE_BAD; } - conf = (cache_server_conf *) ap_get_module_config(r->server->module_config, &cache_module); /* read the etag and cache-control from the entity */ etag = apr_table_get(r->err_headers_out, "Etag"); if (etag == NULL) { @@ -410,14 +423,16 @@ static int cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) /* HEAD requests */ reason = "HTTP HEAD request"; } - else if (ap_cache_liststr(NULL, cc_out, "no-store", NULL)) { + else if (!conf->store_nostore && + ap_cache_liststr(NULL, cc_out, "no-store", NULL)) { /* RFC2616 14.9.2 Cache-Control: no-store response * indicating do not cache, or stop now if you are * trying to cache it */ reason = "Cache-Control: no-store present"; } - else if (ap_cache_liststr(NULL, cc_out, "private", NULL)) { - /* RFC2616 14.9.1 Cache-Control: private + else if (!conf->store_private && + ap_cache_liststr(NULL, cc_out, "private", NULL)) { + /* RFC2616 14.9.1 Cache-Control: private response * this object is marked for this user's eyes only. Behave * as a tunnel. */ @@ -705,7 +720,11 @@ static void * create_cache_config(apr_pool_t *p, server_rec *s) ps->no_last_mod_ignore_set = 0; ps->no_last_mod_ignore = 0; ps->ignorecachecontrol = 0; - ps->ignorecachecontrol_set = 0 ; + ps->ignorecachecontrol_set = 0; + ps->store_private = 0; + ps->store_private_set = 0; + ps->store_nostore = 0; + ps->store_nostore_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; @@ -742,6 +761,14 @@ static void * merge_cache_config(apr_pool_t *p, void *basev, void *overridesv) (overrides->ignorecachecontrol_set == 0) ? base->ignorecachecontrol : overrides->ignorecachecontrol; + ps->store_private = + (overrides->store_private_set == 0) + ? base->store_private + : overrides->store_private; + ps->store_nostore = + (overrides->store_nostore_set == 0) + ? base->store_nostore + : overrides->store_nostore; ps->ignore_headers = (overrides->ignore_headers_set == CACHE_IGNORE_HEADERS_UNSET) ? base->ignore_headers @@ -775,6 +802,32 @@ static const char *set_cache_ignore_cachecontrol(cmd_parms *parms, return NULL; } +static const char *set_cache_store_private(cmd_parms *parms, void *dummy, + int flag) +{ + cache_server_conf *conf; + + conf = + (cache_server_conf *)ap_get_module_config(parms->server->module_config, + &cache_module); + conf->store_private = flag; + conf->store_private_set = 1; + return NULL; +} + +static const char *set_cache_store_nostore(cmd_parms *parms, void *dummy, + int flag) +{ + cache_server_conf *conf; + + conf = + (cache_server_conf *)ap_get_module_config(parms->server->module_config, + &cache_module); + conf->store_nostore = flag; + conf->store_nostore_set = 1; + return NULL; +} + static const char *add_ignore_header(cmd_parms *parms, void *dummy, const char *header) { @@ -909,15 +962,20 @@ static const command_rec cache_cmds[] = "A partial URL prefix below which caching is disabled"), AP_INIT_TAKE1("CacheMaxExpire", set_cache_maxex, NULL, RSRC_CONF, "The maximum time in seconds to cache a document"), - AP_INIT_TAKE1("CacheDefaultExpire", set_cache_defex, NULL, RSRC_CONF, - "The default time in seconds to cache a document"), - AP_INIT_FLAG("CacheIgnoreNoLastMod", set_cache_ignore_no_last_mod, NULL, - RSRC_CONF, - "Ignore Responses where there is no Last Modified Header"), - AP_INIT_FLAG("CacheIgnoreCacheControl", set_cache_ignore_cachecontrol, - NULL, - RSRC_CONF, - "Ignore requests from the client for uncached content"), + AP_INIT_TAKE1("CacheDefaultExpire", set_cache_defex, NULL, RSRC_CONF, + "The default time in seconds to cache a document"), + AP_INIT_FLAG("CacheIgnoreNoLastMod", set_cache_ignore_no_last_mod, NULL, + RSRC_CONF, + "Ignore Responses where there is no Last Modified Header"), + AP_INIT_FLAG("CacheIgnoreCacheControl", set_cache_ignore_cachecontrol, + NULL, RSRC_CONF, + "Ignore requests from the client for uncached content"), + AP_INIT_FLAG("CacheStorePrivate", set_cache_store_private, + NULL, RSRC_CONF, + "Ignore 'Cache-Control: private' and store private content"), + AP_INIT_FLAG("CacheStoreNoStore", set_cache_store_nostore, + NULL, RSRC_CONF, + "Ignore 'Cache-Control: no-store' and store sensitive 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"), diff --git a/modules/cache/mod_cache.h b/modules/cache/mod_cache.h index c0336deb55..8d711be00b 100644 --- a/modules/cache/mod_cache.h +++ b/modules/cache/mod_cache.h @@ -115,13 +115,16 @@ struct cache_disable { /* static information about the local cache */ typedef struct { - apr_array_header_t *cacheenable; /* URLs to cache */ - apr_array_header_t *cachedisable; /* URLs not to cache */ - apr_time_t maxex; /* Maximum time to keep cached files in msecs */ + apr_array_header_t *cacheenable; /* URLs to cache */ + apr_array_header_t *cachedisable; /* URLs not to cache */ + /* Maximum time to keep cached files in msecs */ + apr_time_t maxex; int maxex_set; - apr_time_t defex; /* default time to keep cached file in msecs */ + /* default time to keep cached file in msecs */ + apr_time_t defex; int defex_set; - double factor; /* factor for estimating expires date */ + /* factor for estimating expires date */ + double factor; int factor_set; /** ignore the last-modified header when deciding to cache this request */ int no_last_mod_ignore_set; @@ -129,6 +132,12 @@ typedef struct { /** ignore client's requests for uncached responses */ int ignorecachecontrol; int ignorecachecontrol_set; + /** ignore Cache-Control: private header from server */ + int store_private; + int store_private_set; + /** ignore Cache-Control: no-store header from client or server */ + int store_nostore; + int store_nostore_set; /** store the headers that should not be stored in the cache */ apr_array_header_t *ignore_headers; /* flag if CacheIgnoreHeader has been set */ @@ -144,7 +153,7 @@ struct cache_info { char *content_type; char *etag; char *lastmods; /* last modified of cache entity */ - char *filename; + char *filename; apr_time_t date; apr_time_t lastmod; char lastmod_str[APR_RFC822_DATE_LEN];