]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
mod_cache: Check the request to determine whether we are allowed
authorGraham Leggett <minfrin@apache.org>
Sat, 4 Sep 2010 15:20:30 +0000 (15:20 +0000)
committerGraham Leggett <minfrin@apache.org>
Sat, 4 Sep 2010 15:20:30 +0000 (15:20 +0000)
to return cached content at all, and respect a "Cache-Control:
no-cache" header from a client. Previously, "no-cache" would
behave like "max-age=0".

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@992625 13f79535-47bb-0310-9956-ffa450edef68

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

diff --git a/CHANGES b/CHANGES
index 59b71ed5dcee005087805423cda301c75469f3bc..ba55eb26c2bbd7b957032603bbc57b4edcea58b3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,11 @@
 
 Changes with Apache 2.3.9
 
+  *) mod_cache: Check the request to determine whether we are allowed
+     to return cached content at all, and respect a "Cache-Control:
+     no-cache" header from a client. Previously, "no-cache" would
+     behave like "max-age=0". [Graham Leggett]
+
   *) mod_cache: Use a proper filter context to hold filter data instead
      of misusing the per-request configuration. Fixes a segfault on trunk
      when the normal handler is used. [Graham Leggett]
index 9137fca0b0dd9851c26f8d58479246ad62e6491b..cfc0fdfaa02b231016d8fc0d93a268aca2ee053c 100644 (file)
@@ -203,6 +203,11 @@ int cache_select(request_rec *r)
     if (rv != APR_SUCCESS) {
         return rv;
     }
+
+    if (!ap_cache_check_allowed(r)) {
+        return DECLINED;
+    }
+
     /* go through the cache types till we get a match */
     h = apr_palloc(r->pool, sizeof(cache_handle_t));
 
index 70242a793aecf2bcb0d3787a5defcad159899d64..af18077060226e1baa20bbb0417e41d5f3e04ffc 100644 (file)
@@ -380,6 +380,64 @@ CACHE_DECLARE(apr_status_t) ap_cache_remove_lock(cache_server_conf *conf,
     return apr_file_remove(lockname, r->pool);
 }
 
+CACHE_DECLARE(int) ap_cache_check_allowed(request_rec *r) {
+    const char *cc_cresp, *cc_req;
+    const char *pragma;
+    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.
+     *
+     * This is covered under RFC2616 section 14.9.4 (Cache Revalidation and
+     * Reload Controls).
+     *
+     * - 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");
+
+    if (ap_cache_liststr(NULL, pragma, "no-cache", NULL)
+        || ap_cache_liststr(NULL, cc_req, "no-cache", NULL)) {
+
+        if (!conf->ignorecachecontrol) {
+            return 0;
+        }
+        else {
+            ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+                         "Incoming request is asking for an uncached version of "
+                         "%s, but we have been configured to ignore it and serve "
+                         "cached content anyway", r->unparsed_uri);
+        }
+    }
+
+    if (ap_cache_liststr(NULL, cc_req, "no-store", NULL)) {
+
+        if (!conf->ignorecachecontrol) {
+            /* We're not allowed to serve a cached copy */
+            return 0;
+        }
+        else {
+            ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+                         "Incoming request is asking for a no-store version of "
+                         "%s, but we have been configured to ignore it and serve "
+                         "cached content anyway", r->unparsed_uri);
+        }
+    }
+
+    return 1;
+}
+
+
 CACHE_DECLARE(int) ap_cache_check_freshness(cache_handle_t *h,
                                             request_rec *r)
 {
@@ -402,10 +460,11 @@ CACHE_DECLARE(int) ap_cache_check_freshness(cache_handle_t *h,
      * We now want to check if our cached data is still fresh. This depends
      * on a few things, in this order:
      *
-     * - RFC2616 14.9.4 End to end reload, Cache-Control: no-cache. no-cache in
-     * either the request or the cached response means that we must
-     * revalidate the request unconditionally, overriding any expiration
-     * mechanism. It's equivalent to max-age=0,must-revalidate.
+     * - RFC2616 14.9.4 End to end reload, Cache-Control: no-cache. no-cache
+     * in either the request or the cached response means that we must
+     * perform the request unconditionally, and ignore cached content. We
+     * should never reach here, but if we do, mark the content as stale,
+     * as this is the best we can do.
      *
      * - RFC2616 14.32 Pragma: no-cache This is treated the same as
      * Cache-Control: no-cache.
@@ -445,7 +504,8 @@ CACHE_DECLARE(int) ap_cache_check_freshness(cache_handle_t *h,
 
         ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
                      "Incoming request is asking for a uncached version of "
-                     "%s, but we know better and are ignoring it",
+                     "%s, but we have been configured to ignore it and "
+                     "serve a cached response anyway",
                      r->unparsed_uri);
     }
 
index d2984a45573d76f3c08a4e73e33bfd6c3e9e0fa7..a8183372752d3be8a9a4452aecdb9e74b735e114 100644 (file)
@@ -287,6 +287,15 @@ CACHE_DECLARE(apr_time_t) ap_cache_current_age(cache_info *info, const apr_time_
  */
 CACHE_DECLARE(int) ap_cache_check_freshness(cache_handle_t *h, request_rec *r);
 
+/**
+ * Check the whether the request allows a cached object to be served as per RFC2616
+ * section 14.9.4 (Cache Revalidation and Reload Controls)
+ * @param h cache_handle_t
+ * @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(request_rec *r);
+
 /**
  * Try obtain a cache wide lock on the given cache key.
  *