coar 99/07/28 10:37:22
Modified: . STATUS
src CHANGES
src/include alloc.h
src/main alloc.c
src/modules/standard mod_headers.c mod_negotiation.c
mod_rewrite.c
src/support httpd.exp
Log:
Treat the Vary response header field specially; change the
modules that touch it to use a new routine that only adds a
token if it isn't already present. O(n^2) behaviour as
Dean points out, but absent set/atom operations it seems
a reasonable stopgap for 1.3.7.
PR: 4118 (previously closed with 'use "force-no-vary"')
Reviewed by: Ken Coar
Revision Changes Path
1.727 +1 -8 apache-1.3/STATUS
Index: STATUS
===================================================================
RCS file: /home/cvs/apache-1.3/STATUS,v
retrieving revision 1.726
retrieving revision 1.727
diff -u -r1.726 -r1.727
--- STATUS 1999/07/28 14:06:20 1.726
+++ STATUS 1999/07/28 17:37:05 1.727
@@ -1,5 +1,5 @@
1.3 STATUS:
- Last modified at [$Date: 1999/07/28 14:06:20 $]
+ Last modified at [$Date: 1999/07/28 17:37:05 $]
Release:
@@ -67,13 +67,6 @@
RELEASE SHOWSTOPPERS:
- * The Vary header field stuff is still broken (multiple
- entries occur, etc.). The result is that some browsers (AFAIK at least
- MSIE) are horribly confused by the responses.
- Status: It should be fixed before 1.3.7 went out. For details
- how it should be done, please look at new-httpd mailing list
- archive: Ken, Ralf and Roy have already found consensus in the
- past there.
RELEASE NON-SHOWSTOPPERS BUT WOULD BE REAL NICE TO WRAP THESE UP:
1.1400 +7 -0 apache-1.3/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apache-1.3/src/CHANGES,v
retrieving revision 1.1399
retrieving revision 1.1400
diff -u -r1.1399 -r1.1400
--- CHANGES 1999/07/24 18:48:20 1.1399
+++ CHANGES 1999/07/28 17:37:09 1.1400
@@ -1,5 +1,12 @@
Changes with Apache 1.3.7
+ *) Sanitise "Vary" values by not adding duplicate keywords. A
+ separate routine needs to be used to do this, so any module
+ that frobs "Vary" needs to be changed. The standard modules
+ have all been modified. This solution is somewhat inelegant,
+ but it does the job for now. PR#4118 (better fix than before)
+ [Ken Coar, Roy Fielding]
+
*) Link DSO's with "gcc -shared" instead of "ld -Bshareable" at
least on Linux and FreeBSD for now.
[Rasmus Lerdorf]
1.69 +4 -0 apache-1.3/src/include/alloc.h
Index: alloc.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/alloc.h,v
retrieving revision 1.68
retrieving revision 1.69
diff -u -r1.68 -r1.69
--- alloc.h 1999/05/13 19:44:14 1.68
+++ alloc.h 1999/07/28 17:37:14 1.69
@@ -225,6 +225,10 @@
API_EXPORT(const char *) ap_table_get(const table *, const char *);
API_EXPORT(void) ap_table_set(table *, const char *name, const char *val);
API_EXPORT(void) ap_table_setn(table *, const char *name, const char *val);
+API_EXPORT(void) ap_table_merge_unique_token(table *t, const char *key,
+ const char *val);
+API_EXPORT(void) ap_table_mergen_unique_token(table *t, const char *key,
+ const char *val);
API_EXPORT(void) ap_table_merge(table *, const char *name, const char
*more_val);
API_EXPORT(void) ap_table_mergen(table *, const char *name, const char
*more_val);
API_EXPORT(void) ap_table_unset(table *, const char *key);
1.114 +26 -0 apache-1.3/src/main/alloc.c
Index: alloc.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/alloc.c,v
retrieving revision 1.113
retrieving revision 1.114
diff -u -r1.113 -r1.114
--- alloc.c 1999/05/25 15:32:54 1.113
+++ alloc.c 1999/07/28 17:37:16 1.114
@@ -1346,6 +1346,32 @@
}
}
+/*
+ * Merge an HTTP token into a table entry IFF it isn't already in there.
+ * (Intended primarily to avoid "Vary: host, host".)
+ */
+API_EXPORT(void) ap_table_merge_unique_token(table *t, const char *key,
+ const char *val)
+{
+ const char *curval;
+
+ curval = ap_table_get(t, key);
+ if ((curval == NULL) || (!ap_find_token(t->a.pool, curval, val))) {
+ ap_table_merge(t, key, val);
+ }
+}
+
+API_EXPORT(void) ap_table_mergen_unique_token(table *t, const char *key,
+ const char *val)
+{
+ const char *curval;
+
+ curval = ap_table_get(t, key);
+ if ((curval == NULL) || (!ap_find_token(t->a.pool, curval, val))) {
+ ap_table_mergen(t, key, val);
+ }
+}
+
API_EXPORT(void) ap_table_merge(table *t, const char *key, const char *val)
{
table_entry *elts = (table_entry *) t->a.elts;
1.19 +11 -1 apache-1.3/src/modules/standard/mod_headers.c
Index: mod_headers.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_headers.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- mod_headers.c 1999/01/01 19:05:09 1.18
+++ mod_headers.c 1999/07/28 17:37:18 1.19
@@ -213,7 +213,17 @@
ap_table_addn(r->headers_out, hdr->header, hdr->value);
break;
case hdr_append:
- ap_table_mergen(r->headers_out, hdr->header, hdr->value);
+ /*
+ * "Vary" is particularly sensitive to duplicate tokens;
+ * they break some browsers.
+ */
+ if (strcasecmp(hdr->header, "Vary") == 0) {
+ ap_table_mergen_unique_token(r->headers_out, hdr->header,
+ hdr->value);
+ }
+ else {
+ ap_table_mergen(r->headers_out, hdr->header, hdr->value);
+ }
break;
case hdr_set:
ap_table_setn(r->headers_out, hdr->header, hdr->value);
1.100 +15 -6 apache-1.3/src/modules/standard/mod_negotiation.c
Index: mod_negotiation.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_negotiation.c,v
retrieving revision 1.99
retrieving revision 1.100
diff -u -r1.99 -r1.100
--- mod_negotiation.c 1999/06/04 17:15:51 1.99
+++ mod_negotiation.c 1999/07/28 17:37:18 1.100
@@ -2194,12 +2194,21 @@
if (neg->is_transparent || vary_by_type || vary_by_language ||
vary_by_language || vary_by_charset || vary_by_encoding) {
- ap_table_mergen(hdrs, "Vary", 2 + ap_pstrcat(r->pool,
- neg->is_transparent ? ", negotiate" : "",
- vary_by_type ? ", accept" : "",
- vary_by_language ? ", accept-language" : "",
- vary_by_charset ? ", accept-charset" : "",
- vary_by_encoding ? ", accept-encoding" : "", NULL));
+ if (neg->is_transparent) {
+ ap_table_mergen_unique_token(hdrs, "Vary", "negotiate");
+ }
+ if (vary_by_type) {
+ ap_table_mergen_unique_token(hdrs, "Vary", "accept");
+ }
+ if (vary_by_language) {
+ ap_table_mergen_unique_token(hdrs, "Vary", "accept-language");
+ }
+ if (vary_by_charset) {
+ ap_table_mergen_unique_token(hdrs, "Vary", "accept-charset");
+ }
+ if (vary_by_encoding) {
+ ap_table_mergen_unique_token(hdrs, "Vary", "accept-encoding");
+ }
}
if (neg->is_transparent) { /* Create TCN response header */
1.142 +2 -2 apache-1.3/src/modules/standard/mod_rewrite.c
Index: mod_rewrite.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_rewrite.c,v
retrieving revision 1.141
retrieving revision 1.142
diff -u -r1.141 -r1.142
--- mod_rewrite.c 1999/06/29 08:37:43 1.141
+++ mod_rewrite.c 1999/07/28 17:37:20 1.142
@@ -1880,7 +1880,7 @@
}
vary = ap_table_get(r->notes, VARY_KEY_THIS);
if (vary != NULL) {
- ap_table_merge(r->notes, VARY_KEY, vary);
+ ap_table_merge_unique_token(r->notes, VARY_KEY, vary);
ap_table_unset(r->notes, VARY_KEY_THIS);
}
}
@@ -3781,7 +3781,7 @@
continue;
}
if (strcasecmp(hdrs[i].key, name) == 0) {
- ap_table_merge(r->notes, VARY_KEY_THIS, name);
+ ap_table_merge_unique_token(r->notes, VARY_KEY_THIS, name);
return hdrs[i].val;
}
}
1.22 +2 -0 apache-1.3/src/support/httpd.exp
Index: httpd.exp
===================================================================
RCS file: /home/cvs/apache-1.3/src/support/httpd.exp,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- httpd.exp 1999/06/16 21:27:20 1.21
+++ httpd.exp 1999/07/28 17:37:22 1.22
@@ -337,6 +337,8 @@
ap_table_get
ap_table_merge
ap_table_mergen
+ap_table_mergen_unique_token
+ap_table_merge_unique_token
ap_table_set
ap_table_setn
ap_table_unset