Hi,

On Mon, Mar 4, 2013 at 7:22 PM, ylavic dev <ylavic....@gmail.com> wrote:
> I've been working on a patch for mod_cache to deal (fully) with the
> response header Cache-Control and the no-cache=<header> or private=<header>
> directives.

I realize that, maybe, the patch should have been included in the
message, rather than in an attachment, for it to be read quickly.
So let me reply to myself with the patch below (which is not a big deal)...

Or maybe is there a reason not to include that functionality in
mod_cache, with most of the code being already there ?
I could not find any relative discussion in the list nor anywhere
(about mod_cache, but to say it is not implemented).

Regards,
Yann.

Index: modules/cache/cache_util.c
===================================================================
--- modules/cache/cache_util.c  (revision 1451191)
+++ modules/cache/cache_util.c  (working copy)
@@ -27,7 +27,7 @@

 extern module AP_MODULE_DECLARE_DATA cache_module;

-#define CACHE_SEPARATOR ",   "
+#define CACHE_SEPARATOR ", \t"

 /* Determine if "url" matches the hostname, scheme and port and path
  * in "filter". All but the path comparisons are case-insensitive.
@@ -542,17 +542,84 @@
     }

     /* These come from the cached entity. */
-    if (h->cache_obj->info.control.no_cache
-            || h->cache_obj->info.control.no_cache_header
-            || h->cache_obj->info.control.private_header) {
+    if (h->cache_obj->info.control.no_cache) {
         /*
-         * The cached entity contained Cache-Control: no-cache, or a
-         * no-cache with a header present, or a private with a header
-         * present, so treat as stale causing revalidation.
+         * The cached entity contained Cache-Control: no-cache, so
+         * treat as stale causing revalidation.
          */
         return 0;
     }
+    if (h->cache_obj->info.control.no_cache_header
+            || h->cache_obj->info.control.private_header) {
+        /*
+         * RFC2616 14.9.1: The cached entity contained
+         * Cache-Control: no-cache=, or Cache-Control: private=, with
+         * a header present, hence we are allowed to serve this entity,
+         * but without the specified headers, so let's strip them now,
+         * and fall through the other restrictions.
+         *
+         * Here we assume mixed Cache-Control: no-cache and no-cache=
+         * have been caught above and treated as stale causing revalidation,
+         * leaving here the only no-cache= and/or private= with a header.
+         */
+        char *token;
+        const char *header = apr_table_get(h->resp_hdrs, "Cache-Control");
+        while (header && (token = ap_get_list_item(r->pool, &header))) {
+            /* ap_get_list_item() strips the spurious whitespaces and
+             * lowercases anything (but the quoted-strings) */
+            if (strncmp(token, "no-cache=", 9) == 0) {
+                token += 9;
+            }
+            else if (strncmp(token, "private=", 8) == 0) {
+                token += 8;
+            }
+            else {
+                continue;
+            }

+            if (*token == '"') {
+                /* RFC2616 2.2: quoted-string
+                 * found no ap_*() function to unquote those strings,
+                 * so the job is done here... */
+                char *pos, *start, *end;
+                pos = start = end = token + 1;
+                while (*pos && *pos != '"') {
+                    if (*pos == '\\') {
+                        /* RFC2616 2.2: quoted-pair */
+                        if (end == pos) {
+                            /* duplicate to preserve the original token
+                             * should the quoted-string be invalid */
+                            start = apr_pstrdup(r->pool, start);
+                            pos = end = start + (pos - token) - 1;
+                        }
+                        /* skip the quote */
+                        pos++;
+                    }
+                    if (end != pos) {
+                        *end = *pos;
+                    }
+                    end++;
+                    pos++;
+                }
+                if (*pos == '"' && !*(pos + 1)) {
+                    /* valid quoted-string */
+                    token = start;
+                    *end = '\0';
+                }
+                else {
+                    /* invalid quoted-string, continue? fall through?
+                     * like ap_get_mime_headers_core() we do not check
+                     * headers' names validity, and just fall through,
+                     * is there a tiny chance to unset such a header? */
+                    /*continue;*/
+                }
+            }
+
+            /* strip that header from the response */
+            apr_table_unset(h->resp_hdrs, token);
+        }
+    }
+
     if ((agestr = apr_table_get(h->resp_hdrs, "Age"))) {
         age_c = apr_atoi64(agestr);
     }

Reply via email to