]> granicus.if.org Git - apache/commitdiff
mod_cache: Make sure Vary processing handles multivalued Vary headers and
authorGraham Leggett <minfrin@apache.org>
Tue, 28 May 2013 20:55:01 +0000 (20:55 +0000)
committerGraham Leggett <minfrin@apache.org>
Tue, 28 May 2013 20:55:01 +0000 (20:55 +0000)
multivalued headers referred to via Vary.

trunk patch: http://svn.apache.org/r1478748

Submitted by: minfrin
Reviewed by: jim, wrowe

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

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

diff --git a/CHANGES b/CHANGES
index d11542af530a12d6b11519e9236b311d70766430..9d2ef8dd1c4932e8fc864bd40db750580129a2dc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,9 @@
 
 Changes with Apache 2.4.5
 
+  *) mod_cache: Make sure Vary processing handles multivalued Vary headers and
+     multivalued headers referred to via Vary. [Graham Leggett]
+
   *) mod_cache: When serving from cache, only the last header of a multivalued
      header was taken into account. Fixed. Ensure that Warning headers are
      correctly handled as per RFC2616. [Graham Leggett]
diff --git a/STATUS b/STATUS
index 13dd08d4125a4981c12b7108e390b5b4a45caa01..4b4fbdc96d02f1673d8cc47017aa489c4b216a72 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -90,13 +90,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
  
-    * mod_cache: Make sure Vary processing handles multivalued Vary headers and
-      multivalued headers referred to via Vary.
-      trunk patch: http://svn.apache.org/r1478748
-      2.4.x patch: trunk patch works (minus CHANGES, on condition above backports are
-      done first)
-      +1: minfrin, jim, wrowe
-
     * mod_cache: Make sure that contradictory entity headers present in a 304
       Not Modified response are caught and cause the entity to be removed.
       trunk patch: http://svn.apache.org/r1479117
index 0fb8792c63f048f4e0db308fe635c0794f60b9f6..b1968ff2582624dc359c3b6006af327d37d781dc 100644 (file)
@@ -246,6 +246,7 @@ int cache_select(cache_request_rec *cache, request_rec *r)
         case OK: {
             char *vary = NULL;
             int fresh, mismatch = 0;
+            char *last = NULL;
 
             if (list->provider->recall_headers(h, r) != APR_SUCCESS) {
                 /* try again with next cache type */
@@ -271,25 +272,19 @@ int cache_select(cache_request_rec *cache, request_rec *r)
              *
              * RFC2616 13.6 and 14.44 describe the Vary mechanism.
              */
-            vary = apr_pstrdup(r->pool, apr_table_get(h->resp_hdrs, "Vary"));
-            while (vary && *vary) {
-                char *name = vary;
+            vary = cache_strqtok(
+                    apr_pstrdup(r->pool,
+                            cache_table_getm(r->pool, h->resp_hdrs, "Vary")),
+                    CACHE_SEPARATOR, &last);
+            while (vary) {
                 const char *h1, *h2;
 
-                /* isolate header name */
-                while (*vary && !apr_isspace(*vary) && (*vary != ','))
-                    ++vary;
-                while (apr_isspace(*vary) || (*vary == ',')) {
-                    *vary = '\0';
-                    ++vary;
-                }
-
                 /*
                  * is this header in the request and the header in the cached
                  * request identical? If not, we give up and do a straight get
                  */
-                h1 = apr_table_get(r->headers_in, name);
-                h2 = apr_table_get(h->req_hdrs, name);
+                h1 = cache_table_getm(r->pool, r->headers_in, vary);
+                h2 = cache_table_getm(r->pool, h->req_hdrs, vary);
                 if (h1 == h2) {
                     /* both headers NULL, so a match - do nothing */
                 }
@@ -303,6 +298,7 @@ int cache_select(cache_request_rec *cache, request_rec *r)
                     mismatch = 1;
                     break;
                 }
+                vary = cache_strqtok(NULL, CACHE_SEPARATOR, &last);
             }
 
             /* no vary match, try next provider */
index f82dbdcb211c8a4d225d68fdbef188062c8e2233..f85b1254232314bc35f1b5e59b85b32d67b50e3e 100644 (file)
@@ -27,8 +27,6 @@ extern APR_OPTIONAL_FN_TYPE(ap_cache_generate_key) *cache_generate_key;
 
 extern module AP_MODULE_DECLARE_DATA cache_module;
 
-#define CACHE_SEPARATOR ",   "
-
 /* Determine if "url" matches the hostname, scheme and port and path
  * in "filter". All but the path comparisons are case-insensitive.
  */
@@ -862,7 +860,7 @@ CACHE_DECLARE(char *)ap_cache_generate_name(apr_pool_t *p, int dirlevels,
  * String tokenizer that ignores separator characters within quoted strings
  * and escaped characters, as per RFC2616 section 2.2.
  */
-static char *cache_strqtok(char *str, const char *sep, char **last)
+char *cache_strqtok(char *str, const char *sep, char **last)
 {
     char *token;
     int quoted = 0;
@@ -871,6 +869,10 @@ static char *cache_strqtok(char *str, const char *sep, char **last)
         str = *last;    /* start where we left off */
     }
 
+    if (!str) {         /* no more tokens */
+        return NULL;
+    }
+
     /* skip characters in sep (will terminate at '\0') */
     while (*str && ap_strchr_c(sep, *str)) {
         ++str;
index 0fc2c1b8c20ab79b79d15f2c714984b681a458e0..65321d1fb8a19509f3edabef99b4172db45fcec3 100644 (file)
@@ -99,6 +99,7 @@ extern "C" {
 #define CACHE_LOCKNAME_KEY "mod_cache-lockname"
 #define CACHE_LOCKFILE_KEY "mod_cache-lockfile"
 #define CACHE_CTX_KEY "mod_cache-ctx"
+#define CACHE_SEPARATOR ",   "
 
 /**
  * cache_util.c
@@ -305,6 +306,12 @@ cache_provider_list *cache_get_providers(request_rec *r,
 const char *cache_table_getm(apr_pool_t *p, const apr_table_t *t,
         const char *key);
 
+/**
+ * String tokenizer that ignores separator characters within quoted strings
+ * and escaped characters, as per RFC2616 section 2.2.
+ */
+char *cache_strqtok(char *str, const char *sep, char **last);
+
 #ifdef __cplusplus
 }
 #endif