Here is the patch that strips the "no-cache=" or "private=" specified
headers after the origin server's validation, leaving the only headers
updated by the origin.

Regards,
Yann.

Index: modules/cache/cache_storage.c
===================================================================
--- modules/cache/cache_storage.c       (revision 1456050)
+++ modules/cache/cache_storage.c       (working copy)
@@ -156,6 +156,51 @@
         apr_table_unset(h->resp_hdrs, "Last-Modified");
     }

+    v = apr_table_get(h->resp_hdrs, "Cache-Control");
+    if (v && (h->cache_obj->info.control.no_cache_header ||
+              h->cache_obj->info.control.private_header)) {
+        /*
+         * RFC2616 14.9.1: If the no-cache directive does specify one or more
+         * field-names, then a cache MAY use the response to satisfy a
+         * subsequent request, subject to any other restrictions on caching.
+         * However, the specified field-name(s) MUST NOT be sent in the
+         * response to a subsequent request without successful revalidation
+         * with the origin server.
+         *
+         * Hence we will strip these cached headers (if any) and let the only
+         * ones validated by the origin server.
+         */
+        char *token;
+        apr_size_t len;
+        while ((token = ap_get_list_item(r->pool, &v))) {
+            /* 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;
+            }
+
+            /* RFC2616 14.9: quoted list of field-names */
+            len = strlen(token);
+            if (token[0] == '"' && token[--len] == '"') {
+                (++token)[--len] = '\0';
+                do {
+                    const char *name = ap_cache_tokstr(r->pool, token,
+                                                       (const char**)&token);
+                    if (name) {
+                        /* strip that name header the response */
+                        apr_table_unset(h->resp_hdrs, name);
+                    }
+                } while (token);
+            }
+        }
+    }
+
     /* The HTTP specification says that it is legal to merge duplicate
      * headers into one.  Some browsers that support Cookies don't like
      * merged headers and prefer that each Set-Cookie header is sent

Reply via email to