G'day,
I'm happy to commit this to Squid-2.HEAD as-is. Can you throw it in
a Bugzilla report and spit me the number?
Thanks,
Adrian
On Fri, Feb 08, 2008, Tim Starling wrote:
There are two major sources of suboptimal hit rate on Wikipedia which
relate to the Vary header:
* In Accept-Encoding, we only care whether gzip is present or not, but
IE and Firefox use different whitespace conventions and so each get
separate entries in the cache
* We only care whether the user is logged in or not. Other cookies, such
as pure-JavaScript cookies used by client-side code to store
preferences, unnecessarily degrade our hit rate.
There have been other patches related to this problem, but as far as I'm
aware, they're all special-case, site-specific hacks. My patch adds an
X-Vary-Options response header (hereafter XVO), and thus gives the
origin server fine control over cache variance. In the patch, the XVO
header overrides the Vary header, so the Vary header can still be sent
as usual for compatibility with caches that don't support this feature.
The format of the XVO header is inspired by the format of the Accept
header. As in Vary, XVO is separated by commas into parts which relate
to different request headers. Then those parts are further separated by
semicolons. The first semicolon-separated part is the request header
name, and subsequent parts give name/value pairs separated by equals
signs, defining options relating to the variance of that header.
Two option names are currently defined:
list-contains: splits the request header into comma-separated parts
and varies depending on whether the resulting list contains the option value
string-contains: performs a simple search of the request header and
varies depending on whether it matches.
Multiple such options per header are allowed.
So for example:
X-Vary-Options: Cookie; string-contains=UserID;
string-contains=_session, Accept-Encoding; list-contains=gzip
This would vary the cache on three tests:
* whether the Cookie header contains the string UserID
* whether the Cookie header contains the string _session
* whether the Accept-Encoding header, interpreted as a comma-separated
list, contains the item gzip
The patch refactors all references to the Vary and X-Accelerator-Vary
headers into the functions httpHeaderHasVary() and httpHeaderGetVary()
in HttpHeader.c. It then adds X-Vary-Options to these functions,
interpreting it as a string rather than a list to avoid inappropriate
splitting on whitespace. It puts the resulting combined header into
X-Vary-Options instead of Vary in the base vary marker object, again to
avoid inappropriate list-style interpretation. httpMakeVaryMark() then
interprets this combined header in the way described above.
The added features of the patch are conditional, and are enabled by the
configure option --enable-vary-options. Autoconf and automake will need
to be run after applying this patch.
The interpretation of some non-standards-compliant Vary headers (those
containing semicolons) is changed slightly by this patch regardless of
--enable-vary-options.
The patch is attached and also available at:
http://noc.wikimedia.org/~tstarling/patches/vary_options_upstream.patch
For your review and consideration.
-- Tim Starling
diff -Xdiffx -ru squid-2.6.18.orig/configure.in squid-2.6.18/configure.in
--- squid-2.6.18.orig/configure.in2008-01-10 23:34:23.0 +1100
+++ squid-2.6.18/configure.in 2008-02-07 19:43:23.0 +1100
@@ -1507,6 +1507,16 @@
fi
])
+dnl Enable vary options
+AC_ARG_ENABLE(vary_options,
+[ --enable-vary-options
+ Enable support for the X-Vary-Options header.],
+[ if test $enableval = yes ; then
+echo Enabling support for vary options
+AC_DEFINE(VARY_OPTIONS, 1, [Enable support for the X-Vary-Options
header])
+ fi
+])
+
AC_ARG_ENABLE(follow-x-forwarded-for,
[ --enable-follow-x-forwarded-for
Enable support for following the X-Forwarded-For
diff -Xdiffx -ru squid-2.6.18.orig/src/client_side.c
squid-2.6.18/src/client_side.c
--- squid-2.6.18.orig/src/client_side.c 2008-02-07 19:28:38.0
+1100
+++ squid-2.6.18/src/client_side.c2008-02-08 14:39:38.0 +1100
@@ -735,10 +735,7 @@
request_t *request = http-request;
const char *etag = httpHeaderGetStr(mem-reply-header, HDR_ETAG);
const char *vary = request-vary_headers;
- int has_vary = httpHeaderHas(entry-mem_obj-reply-header,
HDR_VARY);
-#if X_ACCELERATOR_VARY
- has_vary |= httpHeaderHas(entry-mem_obj-reply-header,
HDR_X_ACCELERATOR_VARY);
-#endif
+ int has_vary = httpHeaderHasVary(entry-mem_obj-reply-header);
if (has_vary)
vary = httpMakeVaryMark(request, mem-reply);
@@ -4948,10 +4945,7 @@
varyEvaluateMatch(StoreEntry * entry, request_t *