You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Paul Sutton <pa...@c2.net> on 1998/11/28 20:38:31 UTC

Vary bug in mod_negotiation

mod_negotation has a bug in the way it creates Vary: headers. It only
looks for different *values* for each dimension, and will not notice the
absence of a dimension from one variant is different to the presence of
that dimension in another variant.

For example, if you have files x.html.en and x.html, it will not add
"Accept-Language" to the Vary header. This bug applies to all dimensions
of negotiation. The patch below fixes it.

Paul
--
Paul Sutton, C2Net Europe                    http://www.eu.c2.net/~paul/
Editor, Apache Week .. the latest Apache news http://www.apacheweek.com/

Index: mod_negotiation.c
===================================================================
RCS file: /export/home/cvs/apache-1.3/src/modules/standard/mod_negotiation.c,v
retrieving revision 1.85
diff -u -r1.85 mod_negotiation.c
--- mod_negotiation.c	1998/11/23 09:56:38	1.85
+++ mod_negotiation.c	1998/11/28 19:18:50
@@ -1812,6 +1812,7 @@
     char *sample_language = NULL;
     const char *sample_encoding = NULL;
     char *sample_charset = NULL;
+    int first_variant = 1;
     int vary_by_type = 0;
     int vary_by_language = 0;
     int vary_by_charset = 0;
@@ -1828,6 +1829,7 @@
         char qstr[6];
         long len;
         char lenstr[22];        /* enough for 2^64 */
+        char *lang;
 
         ap_snprintf(qstr, sizeof(qstr), "%1.3f", variant->type_quality);
 
@@ -1843,49 +1845,52 @@
         }
 
         rec = ap_pstrcat(r->pool, "{\"", variant->file_name, "\" ", qstr, NULL);
-        if (variant->type_name) {
-            if (*variant->type_name) {
-                rec = ap_pstrcat(r->pool, rec, " {type ",
-                              variant->type_name, "}", NULL);
-            }
-            if (!sample_type) {
-                sample_type = variant->type_name;
-            }
-            else if (strcmp(sample_type, variant->type_name)) {
-                vary_by_type = 1;
-            }
+
+        if (first_variant) {
+            sample_type = variant->type_name;
+        } else if (strcmp(sample_type ? sample_type : "", 
+                          variant->type_name ? variant->type_name : "")) {
+            vary_by_type = 1;
+        }
+        if (variant->type_name && *variant->type_name) {
+            rec = ap_pstrcat(r->pool, rec, " {type ",
+                             variant->type_name, "}", NULL);
         }
+
         if (variant->content_languages && variant->content_languages->nelts) {
-            char *langs = merge_string_array(r->pool,
-                                           variant->content_languages, ",");
-            rec = ap_pstrcat(r->pool, rec, " {language ", langs, "}", NULL);
-            if (!sample_language) {
-                sample_language = langs;
-            }
-            else if (strcmp(sample_language, langs)) {
-                vary_by_language = 1;
-            }
-        }
-        if (variant->content_encoding) {
-            if (!sample_encoding) {
-                sample_encoding = variant->content_encoding;
-            }
-            else if (strcmp(sample_encoding, variant->content_encoding)) {
-                vary_by_encoding = 1;
-            }
-        }
-        if (variant->content_charset) {
-            if (*variant->content_charset) {
-                rec = ap_pstrcat(r->pool, rec, " {charset ",
-                              variant->content_charset, "}", NULL);
-            }
-            if (!sample_charset) {
-                sample_charset = variant->content_charset;
-            }
-            else if (strcmp(sample_charset, variant->content_charset)) {
-                vary_by_charset = 1;
-            }
+            lang = merge_string_array(r->pool,
+                                      variant->content_languages, ",");
+            rec = ap_pstrcat(r->pool, rec, " {language ", lang, "}", NULL);
+        } else {
+            lang = NULL;
+        }
+        if (first_variant) {
+            sample_language = lang;
+        } else if (strcmp(sample_language ? sample_language : "", 
+                          lang ? lang : "")) {
+            vary_by_language = 1;
+        }
+
+        if (first_variant) {
+            sample_encoding = variant->content_encoding;
+        } else if (strcmp(sample_encoding ? sample_encoding : "",
+                          variant->content_encoding ? 
+                          variant->content_encoding : "")) {
+            vary_by_encoding = 1;
+        }
+
+        if (first_variant) {
+            sample_charset = variant->content_charset;
+        } else if (strcmp(sample_charset ? sample_charset : "",
+                          variant->content_charset ? variant->content_charset
+                          : "")) {
+            vary_by_charset = 1;
+        }
+        if (variant->content_charset && *variant->content_charset) {
+            rec = ap_pstrcat(r->pool, rec, " {charset ",
+                             variant->content_charset, "}", NULL);
         }
+
         if ((len = find_content_length(neg, variant)) != 0) {
             ap_snprintf(lenstr, sizeof(lenstr), "%ld", len);
             rec = ap_pstrcat(r->pool, rec, " {length ", lenstr, "}", NULL);
@@ -1896,6 +1901,8 @@
         if (na_result != na_not_applied) {
             ap_table_mergen(hdrs, "Alternates", rec);
         }
+
+        first_variant = 0;
     }
 
     if (na_result != na_not_applied) {