]> granicus.if.org Git - apache/commitdiff
mod_cache: Honour Cache-Control: no-store in a request.
authorGraham Leggett <minfrin@apache.org>
Tue, 28 May 2013 21:09:34 +0000 (21:09 +0000)
committerGraham Leggett <minfrin@apache.org>
Tue, 28 May 2013 21:09:34 +0000 (21:09 +0000)
trunk patch: http://svn.apache.org/r1479222
2.4.x patch: http://people.apache.org/~minfrin/httpd-mod_cache-nostore2.4.patch

Submitted by: minfrin
Reviewed by: jim, wrowe

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1487121 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
modules/cache/cache_storage.c
modules/cache/cache_util.c
modules/cache/cache_util.h
modules/cache/mod_cache.c

diff --git a/CHANGES b/CHANGES
index ee5b7cd724fbea72f375be9c3d8c3289d754df74..f6d5ffd8ac2171695b801388c7d313b31bcc6782 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,8 @@
 
 Changes with Apache 2.4.5
 
+  *) mod_cache: Honour Cache-Control: no-store in a request. [Graham Leggett]
+
   *) mod_cache: Make sure that contradictory entity headers present in a 304
      Not Modified response are caught and cause the entity to be removed.
      [Graham Leggett]
diff --git a/STATUS b/STATUS
index fcbc5821b9377412e59a648a97a49eaaecc10ba9..cc920ea9cc8da124958ba4a4e87ab25d03dc426a 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -90,11 +90,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
  
-    * mod_cache: Honour Cache-Control: no-store in a request.
-      trunk patch: http://svn.apache.org/r1479222
-      2.4.x patch: http://people.apache.org/~minfrin/httpd-mod_cache-nostore2.4.patch
-      +1: minfrin, jim, wrowe
-
     * mod_cache: Ensure that updated responses to HEAD requests don't get
       mistakenly paired with a previously cached body. Ensure that any existing
       body is removed when a HEAD request is cached.
index b1968ff2582624dc359c3b6006af327d37d781dc..11f98e8f019d51f4ad0815e45c92b324fb2dde9d 100644 (file)
@@ -225,6 +225,13 @@ int cache_select(cache_request_rec *cache, request_rec *r)
         return DECLINED;
     }
 
+    /* if no-cache, we can't serve from the cache, but we may store to the
+     * cache.
+     */
+    if (!ap_cache_check_no_cache(cache, r)) {
+        return DECLINED;
+    }
+
     if (!cache->key) {
         rv = cache_generate_key(r, r->pool, &cache->key);
         if (rv != APR_SUCCESS) {
@@ -232,10 +239,6 @@ int cache_select(cache_request_rec *cache, request_rec *r)
         }
     }
 
-    if (!ap_cache_check_allowed(cache, r)) {
-        return DECLINED;
-    }
-
     /* go through the cache types till we get a match */
     h = apr_palloc(r->pool, sizeof(cache_handle_t));
 
index f85b1254232314bc35f1b5e59b85b32d67b50e3e..7b7fb45c23af1fb48dd9b2774e9e04c32343b186 100644 (file)
@@ -410,9 +410,9 @@ apr_status_t cache_remove_lock(cache_server_conf *conf,
     return apr_file_remove(lockname, r->pool);
 }
 
-CACHE_DECLARE(int) ap_cache_check_allowed(cache_request_rec *cache, request_rec *r) {
-    const char *cc_req;
-    const char *pragma;
+int ap_cache_check_no_cache(cache_request_rec *cache, request_rec *r)
+{
+
     cache_server_conf *conf =
       (cache_server_conf *)ap_get_module_config(r->server->module_config,
                                                 &cache_module);
@@ -427,16 +427,15 @@ CACHE_DECLARE(int) ap_cache_check_allowed(cache_request_rec *cache, request_rec
      * - RFC2616 14.9.4 End to end reload, Cache-Control: no-cache, or Pragma:
      * no-cache. The server MUST NOT use a cached copy when responding to such
      * a request.
-     *
-     * - RFC2616 14.9.2 What May be Stored by Caches. If Cache-Control:
-     * no-store arrives, do not serve from the cache.
      */
 
     /* This value comes from the client's initial request. */
-    cc_req = apr_table_get(r->headers_in, "Cache-Control");
-    pragma = apr_table_get(r->headers_in, "Pragma");
-
-    ap_cache_control(r, &cache->control_in, cc_req, pragma, r->headers_in);
+    if (!cache->control_in.parsed) {
+        const char *cc_req = cache_table_getm(r->pool, r->headers_in,
+                "Cache-Control");
+        const char *pragma = cache_table_getm(r->pool, r->headers_in, "Pragma");
+        ap_cache_control(r, &cache->control_in, cc_req, pragma, r->headers_in);
+    }
 
     if (cache->control_in.no_cache) {
 
@@ -451,6 +450,32 @@ CACHE_DECLARE(int) ap_cache_check_allowed(cache_request_rec *cache, request_rec
         }
     }
 
+    return 1;
+}
+
+int ap_cache_check_no_store(cache_request_rec *cache, request_rec *r)
+{
+
+    cache_server_conf *conf =
+      (cache_server_conf *)ap_get_module_config(r->server->module_config,
+                                                &cache_module);
+
+    /*
+     * At this point, we may have data cached, but the request may have
+     * specified that cached data may not be used in a response.
+     *
+     * - RFC2616 14.9.2 What May be Stored by Caches. If Cache-Control:
+     * no-store arrives, do not serve from or store to the cache.
+     */
+
+    /* This value comes from the client's initial request. */
+    if (!cache->control_in.parsed) {
+        const char *cc_req = cache_table_getm(r->pool, r->headers_in,
+                "Cache-Control");
+        const char *pragma = cache_table_getm(r->pool, r->headers_in, "Pragma");
+        ap_cache_control(r, &cache->control_in, cc_req, pragma, r->headers_in);
+    }
+
     if (cache->control_in.no_store) {
 
         if (!conf->ignorecachecontrol) {
@@ -468,7 +493,6 @@ CACHE_DECLARE(int) ap_cache_check_allowed(cache_request_rec *cache, request_rec
     return 1;
 }
 
-
 int cache_check_freshness(cache_handle_t *h, cache_request_rec *cache,
         request_rec *r)
 {
index 65321d1fb8a19509f3edabef99b4172db45fcec3..3a54fadd067f6604a935f5a24a90e94a66c7b25f 100644 (file)
@@ -239,7 +239,16 @@ typedef struct {
  * @param r request_rec
  * @return 0 ==> cache object may not be served, 1 ==> cache object may be served
  */
-CACHE_DECLARE(int) ap_cache_check_allowed(cache_request_rec *cache, request_rec *r);
+int ap_cache_check_no_cache(cache_request_rec *cache, request_rec *r);
+
+/**
+ * Check the whether the request allows a cached object to be stored as per RFC2616
+ * section 14.9.2 (What May be Stored by Caches)
+ * @param cache cache_request_rec
+ * @param r request_rec
+ * @return 0 ==> cache object may not be served, 1 ==> cache object may be served
+ */
+int ap_cache_check_no_store(cache_request_rec *cache, request_rec *r);
 
 /**
  * Check the freshness of the cache object per RFC2616 section 13.2 (Expiration Model)
index de61ba12c02548539deec68e5bf182f904909292..9258ebd56466dcf7fee3068868f49d4f94639500 100644 (file)
@@ -102,6 +102,9 @@ static int cache_quick_handler(request_rec *r, int lookup)
     /*
      * Are we allowed to serve cached info at all?
      */
+    if (!ap_cache_check_no_store(cache, r)) {
+        return DECLINED;
+    }
 
     /* find certain cache controlling headers */
     auth = apr_table_get(r->headers_in, "Authorization");
@@ -401,6 +404,13 @@ static int cache_handler(request_rec *r)
     /* save away the possible providers */
     cache->providers = providers;
 
+    /*
+     * Are we allowed to serve cached info at all?
+     */
+    if (!ap_cache_check_no_store(cache, r)) {
+        return DECLINED;
+    }
+
     /* Are we PUT/POST/DELETE? If so, prepare to invalidate the cached entities.
      */
     switch (r->method_number) {