mirror of
https://github.com/apache/httpd.git
synced 2026-01-06 09:01:14 +03:00
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
This commit is contained in:
3
CHANGES
3
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]
|
||||
|
||||
|
||||
@@ -235,24 +235,33 @@ header.</description>
|
||||
|
||||
<directivesynopsis>
|
||||
<name>CacheIgnoreCacheControl</name>
|
||||
<description>Ignore the fact that the client requested the content not be
|
||||
cached.</description>
|
||||
<description>Ignore request to not serve cached content to client</description>
|
||||
<syntax>CacheIgnoreCacheControl On|Off</syntax>
|
||||
<default>CacheIgnoreCacheControl Off</default>
|
||||
<contextlist><context>server config</context><context>virtual host</context>
|
||||
</contextlist>
|
||||
|
||||
<usage>
|
||||
<p>Ordinarily, documents with no-cache or no-store header values will not be stored in the cache.
|
||||
The <directive>CacheIgnoreCacheControl</directive> directive allows this behavior to be overridden.
|
||||
<directive>CacheIgnoreCacheControl</directive> 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
|
||||
<em>never</em> be cached.</p>
|
||||
<p>Ordinarily, requests containing a Cache-Control: no-cache or
|
||||
Pragma: no-cache header value will not be served from the cache. The
|
||||
<directive>CacheIgnoreCacheControl</directive> directive allows this
|
||||
behavior to be overridden. <directive>CacheIgnoreCacheControl</directive>
|
||||
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 <em>never</em> be cached.</p>
|
||||
|
||||
<example>
|
||||
CacheIgnoreCacheControl On
|
||||
</example>
|
||||
|
||||
<note type="warning"><title>Warning:</title>
|
||||
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.
|
||||
</note>
|
||||
</usage>
|
||||
<seealso><directive module="mod_cache">CacheStorePrivate</directive></seealso>
|
||||
<seealso><directive module="mod_cache">CacheStoreNoStore</directive></seealso>
|
||||
</directivesynopsis>
|
||||
|
||||
<directivesynopsis>
|
||||
@@ -343,4 +352,66 @@ LastModified date.</description>
|
||||
</usage>
|
||||
</directivesynopsis>
|
||||
|
||||
<directivesynopsis>
|
||||
<name>CacheStorePrivate</name>
|
||||
<description>Attempt to cache responses that the server has marked as private</description>
|
||||
<syntax>CacheStorePrivate On|Off</syntax>
|
||||
<default>CacheStorePrivate Off</default>
|
||||
<contextlist><context>server config</context><context>virtual host</context>
|
||||
</contextlist>
|
||||
|
||||
<usage>
|
||||
<p>Ordinarily, responses with Cache-Control: private header values will not
|
||||
be stored in the cache. The <directive>CacheStorePrivate</directive>
|
||||
directive allows this behavior to be overridden.
|
||||
<directive>CacheStorePrivate</directive> On
|
||||
tells the server to attempt to cache the resource even if it contains
|
||||
private header values. Resources requiring authorization will
|
||||
<em>never</em> be cached.</p>
|
||||
|
||||
<example>
|
||||
CacheStorePrivate On
|
||||
</example>
|
||||
|
||||
<note type="warning"><title>Warning:</title>
|
||||
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.
|
||||
</note>
|
||||
</usage>
|
||||
<seealso><directive module="mod_cache">CacheIgnoreCacheControl</directive></seealso>
|
||||
<seealso><directive module="mod_cache">CacheStoreNoStore</directive></seealso>
|
||||
</directivesynopsis>
|
||||
|
||||
<directivesynopsis>
|
||||
<name>CacheStoreNoStore</name>
|
||||
<description>Attempt to cache requests or responses that have been marked as no-store.</description>
|
||||
<syntax>CacheStoreNoStore On|Off</syntax>
|
||||
<default>CacheStoreNoStore Off</default>
|
||||
<contextlist><context>server config</context><context>virtual host</context>
|
||||
</contextlist>
|
||||
|
||||
<usage>
|
||||
<p>Ordinarily, requests or responses with Cache-Control: no-store header
|
||||
values will not be stored in the cache. The
|
||||
<directive>CacheStoreNoCache</directive> directive allows this
|
||||
behavior to be overridden. <directive>CacheStoreNoCache</directive> On
|
||||
tells the server to attempt to cache the resource even if it contains
|
||||
no-store header values. Resources requiring authorization will
|
||||
<em>never</em> be cached.</p>
|
||||
|
||||
<example>
|
||||
CacheStoreNoStore On
|
||||
</example>
|
||||
|
||||
<note type="warning"><title>Warning:</title>
|
||||
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.
|
||||
</note>
|
||||
</usage>
|
||||
<seealso><directive module="mod_cache">CacheIgnoreCacheControl</directive></seealso>
|
||||
<seealso><directive module="mod_cache">CacheStorePrivate</directive></seealso>
|
||||
</directivesynopsis>
|
||||
</modulesynopsis>
|
||||
|
||||
106
modules/cache/mod_cache.c
vendored
106
modules/cache/mod_cache.c
vendored
@@ -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"),
|
||||
|
||||
21
modules/cache/mod_cache.h
vendored
21
modules/cache/mod_cache.h
vendored
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user