---------------------
PatchSet 1347 
Date: 2001/01/18 20:12:42
Author: hno
Branch: vary-2_3
Tag: (none) 
Log:
Back-ported changes from 'vary'

Members: 
	src/HttpHeader.c:1.1.1.3.4.2->1.1.1.3.4.2.4.1 
	src/HttpReply.c:1.1.1.3.4.1->1.1.1.3.4.1.6.1 
	src/HttpRequest.c:1.1.1.3.4.1->1.1.1.3.4.1.6.1 
	src/cf.data.pre:1.1.1.3.4.3->1.1.1.3.4.3.4.1 
	src/client_side.c:1.1.1.3.4.6->1.1.1.3.4.6.4.1 
	src/enums.h:1.1.1.3.4.2->1.1.1.3.4.2.4.1 
	src/ftp.c:1.1.1.3.4.3->1.1.1.3.4.3.4.1 
	src/htcp.c:1.1.1.2.4.1->1.1.1.2.4.1.6.1 
	src/http.c:1.1.1.3.4.3->1.1.1.3.4.3.4.1 
	src/neighbors.c:1.1.1.3.4.1->1.1.1.3.4.1.6.1 
	src/peer_digest.c:1.1.1.3.4.1->1.1.1.3.4.1.6.1 
	src/peer_select.c:1.1.1.3.4.1->1.1.1.3.4.1.6.1 
	src/protos.h:1.1.1.3.4.1->1.1.1.3.4.1.6.1 
	src/store.c:1.1.1.3.4.5->1.1.1.3.4.5.4.1 
	src/store_client.c:1.1.1.3.4.2->1.1.1.3.4.2.6.1 
	src/store_key_md5.c:1.1.1.3.4.1->1.1.1.3.4.1.6.1 
	src/store_swapmeta.c:1.1.1.2.4.2->1.1.1.2.4.2.4.1 
	src/structs.h:1.1.1.3.4.2->1.1.1.3.4.2.6.1 

Index: squid/src/HttpHeader.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/HttpHeader.c,v
retrieving revision 1.1.1.3.4.2
retrieving revision 1.1.1.3.4.2.4.1
diff -u -r1.1.1.3.4.2 -r1.1.1.3.4.2.4.1
--- squid/src/HttpHeader.c	31 Dec 2000 05:24:17 -0000	1.1.1.3.4.2
+++ squid/src/HttpHeader.c	18 Jan 2001 20:12:42 -0000	1.1.1.3.4.2.4.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpHeader.c,v 1.1.1.3.4.2 2000/12/31 05:24:17 hno Exp $
+ * $Id: HttpHeader.c,v 1.1.1.3.4.2.4.1 2001/01/18 20:12:42 hno Exp $
  *
  * DEBUG: section 55    HTTP Header
  * AUTHOR: Alex Rousskov
@@ -122,6 +122,7 @@
     {"X-Forwarded-For", HDR_X_FORWARDED_FOR, ftStr},
     {"X-Request-URI", HDR_X_REQUEST_URI, ftStr},
     {"X-Squid-Error", HDR_X_SQUID_ERROR, ftStr},
+    {"Negotiate", HDR_NEGOTIATE, ftStr},
     {"Other:", HDR_OTHER, ftStr}	/* ':' will not allow matches */
 };
 static HttpHeaderFieldInfo *Headers = NULL;
@@ -602,6 +603,21 @@
     return s;
 }
 
+/* return a string or list of entries with the same id separated by ',' and ws */
+String
+httpHeaderGetStrOrList(const HttpHeader * hdr, http_hdr_type id)
+{
+    const char *str;
+    String s;
+
+    if (CBIT_TEST(ListHeadersMask, id))
+	s = httpHeaderGetList(hdr, id);
+    else {
+	str = httpHeaderGetStr(hdr, id);
+	stringInit(&s, str);
+    }
+    return s;
+}
 
 /* test if a field is present */
 int
Index: squid/src/HttpReply.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/HttpReply.c,v
retrieving revision 1.1.1.3.4.1
retrieving revision 1.1.1.3.4.1.6.1
diff -u -r1.1.1.3.4.1 -r1.1.1.3.4.1.6.1
--- squid/src/HttpReply.c	17 Apr 2000 00:56:53 -0000	1.1.1.3.4.1
+++ squid/src/HttpReply.c	18 Jan 2001 20:12:42 -0000	1.1.1.3.4.1.6.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpReply.c,v 1.1.1.3.4.1 2000/04/17 00:56:53 hno Exp $
+ * $Id: HttpReply.c,v 1.1.1.3.4.1.6.1 2001/01/18 20:12:42 hno Exp $
  *
  * DEBUG: section 58    HTTP Reply (Response)
  * AUTHOR: Alex Rousskov
@@ -314,6 +314,13 @@
 		return squid_curtime;
 	}
     }
+    if (Config.onoff.vary_ignore_expire &&
+	httpHeaderHas(&rep->header, HDR_VARY)) {
+	const time_t d = httpHeaderGetTime(&rep->header, HDR_DATE);
+	const time_t e = httpHeaderGetTime(&rep->header, HDR_EXPIRES);
+	if (d == e)
+	    return -1;
+    }
     if (httpHeaderHas(&rep->header, HDR_EXPIRES)) {
 	const time_t e = httpHeaderGetTime(&rep->header, HDR_EXPIRES);
 	/*
Index: squid/src/HttpRequest.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/HttpRequest.c,v
retrieving revision 1.1.1.3.4.1
retrieving revision 1.1.1.3.4.1.6.1
diff -u -r1.1.1.3.4.1 -r1.1.1.3.4.1.6.1
--- squid/src/HttpRequest.c	17 Apr 2000 00:56:53 -0000	1.1.1.3.4.1
+++ squid/src/HttpRequest.c	18 Jan 2001 20:12:42 -0000	1.1.1.3.4.1.6.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpRequest.c,v 1.1.1.3.4.1 2000/04/17 00:56:53 hno Exp $
+ * $Id: HttpRequest.c,v 1.1.1.3.4.1.6.1 2001/01/18 20:12:42 hno Exp $
  *
  * DEBUG: section 73    HTTP Request
  * AUTHOR: Duane Wessels
@@ -57,6 +57,7 @@
     assert(req);
     safe_free(req->body);
     safe_free(req->canonical);
+    safe_free(req->vary_headers);
     stringClean(&req->urlpath);
     httpHeaderClean(&req->header);
     if (req->cache_control)
Index: squid/src/cf.data.pre
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/cf.data.pre,v
retrieving revision 1.1.1.3.4.3
retrieving revision 1.1.1.3.4.3.4.1
diff -u -r1.1.1.3.4.3 -r1.1.1.3.4.3.4.1
--- squid/src/cf.data.pre	1 Jul 2000 12:05:14 -0000	1.1.1.3.4.3
+++ squid/src/cf.data.pre	18 Jan 2001 20:12:42 -0000	1.1.1.3.4.3.4.1
@@ -1,6 +1,6 @@
 
 #
-# $Id: cf.data.pre,v 1.1.1.3.4.3 2000/07/01 12:05:14 hno Exp $
+# $Id: cf.data.pre,v 1.1.1.3.4.3.4.1 2001/01/18 20:12:42 hno Exp $
 #
 #
 # SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -3235,5 +3235,21 @@
 client_persistent_connections on
 server_persistent_connections on
 DOC_END
+
+NAME: vary_ignore_expire
+COMMENT: on|off
+TYPE: onoff
+LOC: Config.onoff.vary_ignore_expire
+DEFAULT: off
+DOC_START
+	Many HTTP servers supporting Vary gives such objects
+	immediate expiry time with no cache-control header
+	when requested by a HTTP/1.0 client. This option
+	enables Squid to ignore such expiry times until
+	HTTP/1.1 is fully implemented.
+	WARNING: This may eventually cause some varying
+	objects not intended for caching to get cached.
+DOC_END
+
 EOF
 
Index: squid/src/client_side.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/client_side.c,v
retrieving revision 1.1.1.3.4.6
retrieving revision 1.1.1.3.4.6.4.1
diff -u -r1.1.1.3.4.6 -r1.1.1.3.4.6.4.1
--- squid/src/client_side.c	21 Oct 2000 14:44:59 -0000	1.1.1.3.4.6
+++ squid/src/client_side.c	18 Jan 2001 20:12:42 -0000	1.1.1.3.4.6.4.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.c,v 1.1.1.3.4.6 2000/10/21 14:44:59 hno Exp $
+ * $Id: client_side.c,v 1.1.1.3.4.6.4.1 2001/01/18 20:12:42 hno Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -533,6 +533,8 @@
     StoreEntry *entry;
     ErrorState *err = NULL;
     HttpReply *r;
+    http_status status = HTTP_NOT_FOUND;
+    http_version_t version;
     debug(33, 3) ("Config2.onoff.enable_purge = %d\n", Config2.onoff.enable_purge);
     if (!Config2.onoff.enable_purge) {
 	http->log_type = LOG_TCP_DENIED;
@@ -543,19 +545,71 @@
 	errorAppendEntry(http->entry, err);
 	return;
     }
+    /* Release both IP cache */
+    ipcacheInvalidate(http->request->host);
+
+    if (!http->flags.purging) {
+	/* Try to find a base entry */
+	http->flags.purging = 1;
+	entry = storeGetPublicByRequestMethod(http->request, METHOD_GET);
+	if (!entry)
+	    entry = storeGetPublicByRequestMethod(http->request, METHOD_HEAD);
+	if (entry) {
+	    /* Swap in the metadata */
+	    http->entry = entry;
+	    storeLockObject(http->entry);
+	    storeCreateMemObject(http->entry, http->uri, http->log_uri);
+	    http->entry->mem_obj->method = http->request->method;
+	    http->sc = storeClientListAdd(http->entry, http);
+	    http->log_type = LOG_TCP_HIT;
+	    storeClientCopy(http->sc, http->entry,
+		http->out.offset,
+		http->out.offset,
+		CLIENT_SOCK_SZ,
+		memAllocate(MEM_CLIENT_SOCK_BUF),
+		clientCacheHit,
+		http);
+	    return;
+	}
+    }
     http->log_type = LOG_TCP_MISS;
-    if ((entry = storeGetPublic(http->uri, METHOD_GET)) == NULL) {
-	http->http_code = HTTP_NOT_FOUND;
-    } else {
+    /* Release the cached URI */
+    entry = storeGetPublicByRequestMethod(http->request, METHOD_GET);
+    if (entry) {
+	debug(33, 4) ("clientPurgeRequest: GET '%s'\n",
+	    storeUrl(entry));
 	storeRelease(entry);
-	http->http_code = HTTP_OK;
+	status = HTTP_OK;
+    }
+    entry = storeGetPublicByRequestMethod(http->request, METHOD_HEAD);
+    if (entry) {
+	debug(33, 4) ("clientPurgeRequest: HEAD '%s'\n",
+	    storeUrl(entry));
+	storeRelease(entry);
+	status = HTTP_OK;
+    }
+    /* And for Vary, release the base URI if none of the headers was included in the request */
+    if (http->request->vary_headers && !strstr(http->request->vary_headers,"=")) {
+	entry = storeGetPublic(urlCanonical(http->request), METHOD_GET);
+	if (entry) {
+	    debug(33, 4) ("clientPurgeRequest: Vary GET '%s'\n",
+		storeUrl(entry));
+	    storeRelease(entry);
+	    status = HTTP_OK;
+	}
+	entry = storeGetPublic(urlCanonical(http->request), METHOD_HEAD);
+	if (entry) {
+	    debug(33, 4) ("clientPurgeRequest: Vary HEAD '%s'\n",
+		storeUrl(entry));
+	    storeRelease(entry);
+	    status = HTTP_OK;
+	}
     }
-    debug(33, 4) ("clientPurgeRequest: Not modified '%s'\n",
-	storeUrl(entry));
     /*
      * Make a new entry to hold the reply to be written
      * to the client.
      */
+    http->http_code = status;
     http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags);
     httpReplyReset(r = http->entry->mem_obj->reply);
     httpReplySetHeaders(r, 1.0, http->http_code, NULL, NULL, 0, 0, -1);
@@ -1313,6 +1367,45 @@
      * Got the headers, now grok them
      */
     assert(http->log_type == LOG_TCP_HIT);
+    switch (varyEvaluateMatch(e, r)) {
+    case VARY_NONE:
+	/* No variance detected. Continue as normal */
+	break;
+    case VARY_MATCH:
+    	/* This is the correct entity for this request. Continue */
+	debug(33, 2) ("clientProcessHit: Vary MATCH!\n");
+	break;
+    case VARY_OTHER:
+    	/* This is not the correct entity for this request. We need
+	 * to requery the cache.
+	 */
+	memFree(buf, MEM_CLIENT_SOCK_BUF);
+	http->entry = NULL;
+	storeUnregister(http->sc, e, http);
+	http->sc = NULL;
+	storeUnlockObject(e);
+	/* Note: varyEvalyateMatch updates the request with vary information
+	 * so we only get here once. (it also takes care of cancelling loops)
+	 */
+	debug(33, 2) ("clientProcessHit: Vary detected!\n");
+	clientProcessRequest(http);
+	return; 
+    case VARY_CANCEL:
+	/* varyEvaluateMatch found a object loop. Process as miss */
+	debug(33, 1) ("clientProcessHit: Vary object loop!\n");
+	memFree(buf, MEM_CLIENT_SOCK_BUF);
+	clientProcessMiss(http);
+	return;
+    }
+    if (r->method == METHOD_PURGE) {
+	memFree(buf, MEM_CLIENT_SOCK_BUF);
+	http->entry = NULL;
+	storeUnregister(http->sc, e, http);
+	http->sc = NULL;
+	storeUnlockObject(e);
+	clientPurgeRequest(http);
+	return;
+    }
     if (checkNegativeHit(e)) {
 	http->log_type = LOG_TCP_NEGATIVE_HIT;
 	clientSendMoreData(data, buf, size);
@@ -1866,11 +1959,7 @@
 {
     request_t *r = http->request;
     StoreEntry *e;
-    e = http->entry = storeGetPublic(http->uri, r->method);
-    if (r->method == METHOD_HEAD && e == NULL) {
-	/* We can generate a HEAD reply from a cached GET object */
-	e = http->entry = storeGetPublic(http->uri, METHOD_GET);
-    }
+    e = http->entry = storeGetPublicByRequest(r);
 #if USE_CACHE_DIGESTS
     http->lookup_type = e ? "HIT" : "MISS";
 #endif
@@ -2023,6 +2112,10 @@
 	storeUnlockObject(http->entry);
 	http->entry = NULL;
     }
+    if (r->method == METHOD_PURGE) {
+	clientPurgeRequest(http);
+	return;
+    }
     if (clientOnlyIfCached(http)) {
 	clientProcessOnlyIfCachedMiss(http);
 	return;
@@ -2851,3 +2944,51 @@
     }
     NHttpSockets = 0;
 }
+
+int
+varyEvaluateMatch(StoreEntry *entry, request_t *request)
+{
+    const char *vary = request->vary_headers;
+    int has_vary = httpHeaderHas(&entry->mem_obj->reply->header, HDR_VARY);
+    if (!has_vary || !entry->mem_obj->vary_headers) {
+	if (vary) {
+	    /* Oops... something odd is going on here.. */
+	    debug(33, 1) ("varyEvaluateMatch: Oops. Not a Vary object on second attempt, '%s' '%s'\n",
+	    	entry->mem_obj->url, vary);
+	    safe_free(request->vary_headers);
+	    return VARY_CANCEL;
+	}
+	if (!has_vary) {
+	    /* This is not a varying object */
+	    return VARY_NONE;
+	}
+	/* virtual "vary" object found. Calculate the vary key and
+	 * continue the search
+	 */
+	vary = request->vary_headers = xstrdup(httpMakeVaryMark(request, entry->mem_obj->reply));
+	if (vary)
+	    return VARY_OTHER;
+	else {
+	    /* Ouch.. we cannot handle this kind of variance */
+	    /* XXX This cannot really happen, but just to be complete */
+	    return VARY_CANCEL;
+	}
+    } else {
+	if (!vary)
+	    vary = request->vary_headers = xstrdup(httpMakeVaryMark(request, entry->mem_obj->reply));
+	if (!vary) {
+	    /* Ouch.. we cannot handle this kind of variance */
+	    /* XXX This cannot really happen, but just to be complete */
+	    return VARY_CANCEL;
+	} else if (strcmp(vary, entry->mem_obj->vary_headers) == 0) {
+	    return VARY_MATCH;
+	} else {
+	    /* Oops.. we have already been here and still haven't
+	     * found the requested variant. Bail out
+	     */
+	    debug(33, 1) ("varyEvaluateMatch: Oops. Not a Vary match on second attempt, '%s' '%s'\n",
+	    	entry->mem_obj->url, vary);
+	    return VARY_CANCEL;
+	}
+    }
+}
Index: squid/src/enums.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/enums.h,v
retrieving revision 1.1.1.3.4.2
retrieving revision 1.1.1.3.4.2.4.1
diff -u -r1.1.1.3.4.2 -r1.1.1.3.4.2.4.1
--- squid/src/enums.h	1 Jul 2000 12:05:14 -0000	1.1.1.3.4.2
+++ squid/src/enums.h	18 Jan 2001 20:12:43 -0000	1.1.1.3.4.2.4.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: enums.h,v 1.1.1.3.4.2 2000/07/01 12:05:14 hno Exp $
+ * $Id: enums.h,v 1.1.1.3.4.2.4.1 2001/01/18 20:12:43 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -238,6 +238,7 @@
     HDR_X_FORWARDED_FOR,
     HDR_X_REQUEST_URI,		/* appended if ADD_X_REQUEST_URI is #defined */
     HDR_X_SQUID_ERROR,
+    HDR_NEGOTIATE,
     HDR_OTHER,
     HDR_ENUM_END
 } http_hdr_type;
@@ -606,6 +607,7 @@
     STORE_META_STD,		/* standard metadata */
     STORE_META_HITMETERING,	/* reserved for hit metering */
     STORE_META_VALID,
+    STORE_META_VARY_HEADERS,	/* Stores Vary request headers */
     STORE_META_END
 };
 
@@ -664,3 +666,14 @@
     SWAPDIR_ASYNCUFS,
     SWAPDIR_MAX
 } swapdir_t;
+
+/*
+ * Return codes from checkVary(request)
+ */
+enum {
+    VARY_NONE,
+    VARY_MATCH,
+    VARY_OTHER,
+    VARY_CANCEL
+};
+
Index: squid/src/ftp.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/ftp.c,v
retrieving revision 1.1.1.3.4.3
retrieving revision 1.1.1.3.4.3.4.1
diff -u -r1.1.1.3.4.3 -r1.1.1.3.4.3.4.1
--- squid/src/ftp.c	31 Dec 2000 05:24:17 -0000	1.1.1.3.4.3
+++ squid/src/ftp.c	18 Jan 2001 20:12:43 -0000	1.1.1.3.4.3.4.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ftp.c,v 1.1.1.3.4.3 2000/12/31 05:24:17 hno Exp $
+ * $Id: ftp.c,v 1.1.1.3.4.3.4.1 2001/01/18 20:12:43 hno Exp $
  *
  * DEBUG: section 9     File Transfer Protocol (FTP)
  * AUTHOR: Harvest Derived
@@ -1043,8 +1043,7 @@
     const char *url = storeUrl(entry);
     FtpStateData *ftpState = xcalloc(1, sizeof(FtpStateData));
     HttpReply *reply;
-    StoreEntry *pe = NULL;
-    const cache_key *key = NULL;
+
     cbdataAdd(ftpState, cbdataXfree, 0);
     debug(9, 3) ("ftpStart: '%s'\n", url);
     Counter.server.all.requests++;
@@ -1075,10 +1074,6 @@
 	    snprintf(realm, 8192, "ftp %s port %d",
 		ftpState->user, request->port);
 	}
-	/* eject any old cached object */
-	key = storeKeyPublic(entry->mem_obj->url, entry->mem_obj->method);
-	if ((pe = storeGet(key)) != NULL)
-	    storeRelease(pe);
 	/* create reply */
 	reply = entry->mem_obj->reply;
 	assert(reply != NULL);
@@ -2453,8 +2448,8 @@
     const char *filename = NULL;
     const char *t = NULL;
     StoreEntry *e = ftpState->entry;
-    StoreEntry *pe = NULL;
     http_reply *reply = e->mem_obj->reply;
+
     if (ftpState->flags.http_header_sent)
 	return;
     ftpState->flags.http_header_sent = 1;
@@ -2503,12 +2498,8 @@
     storeTimestampsSet(e);
     if (ftpState->flags.authenticated) {
 	/*
-	 * Authenticated requests can't be cached. Eject any old cached
-	 * object
+	 * Authenticated requests can't be cached.
 	 */
-	pe = storeGetPublic(e->mem_obj->url, e->mem_obj->method);
-	if (pe)
-	    storeRelease(pe);
 	storeRelease(e);
     } else if (EBIT_TEST(e->flags, ENTRY_CACHABLE) && !ftpState->restarted_offset) {
 	storeSetPublicKey(e);
Index: squid/src/htcp.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/htcp.c,v
retrieving revision 1.1.1.2.4.1
retrieving revision 1.1.1.2.4.1.6.1
diff -u -r1.1.1.2.4.1 -r1.1.1.2.4.1.6.1
--- squid/src/htcp.c	17 Apr 2000 00:56:53 -0000	1.1.1.2.4.1
+++ squid/src/htcp.c	18 Jan 2001 20:12:43 -0000	1.1.1.2.4.1.6.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: htcp.c,v 1.1.1.2.4.1 2000/04/17 00:56:53 hno Exp $
+ * $Id: htcp.c,v 1.1.1.2.4.1.6.1 2001/01/18 20:12:43 hno Exp $
  *
  * DEBUG: section 31    Hypertext Caching Protocol
  * AUTHOR: Duane Wesssels
@@ -614,16 +614,8 @@
 {
     request_t *request;
     method_t m = urlParseMethod(s->method);
-    StoreEntry *e = storeGetPublic(s->uri, m);
+    StoreEntry *e = NULL, *hit = NULL;
     char *blk_end;
-    if (NULL == e) {
-	debug(31, 3) ("htcpCheckHit: NO; public object not found\n");
-	return NULL;
-    }
-    if (!storeEntryValidToSend(e)) {
-	debug(31, 3) ("htcpCheckHit: NO; entry not valid to send\n");
-	return NULL;
-    }
     request = urlParse(m, s->uri);
     if (NULL == request) {
 	debug(31, 3) ("htcpCheckHit: NO; failed to parse URL\n");
@@ -632,15 +624,26 @@
     blk_end = s->req_hdrs + strlen(s->req_hdrs);
     if (!httpHeaderParse(&request->header, s->req_hdrs, blk_end)) {
 	debug(31, 3) ("htcpCheckHit: NO; failed to parse request headers\n");
-	e = NULL;
-    } else if (refreshCheckHTCP(e, request)) {
+	goto miss;
+    }
+    e = storeGetPublicByRequest(request);
+    if (NULL == e) {
+	debug(31, 3) ("htcpCheckHit: NO; public object not found\n");
+	goto miss;
+    }
+    if (!storeEntryValidToSend(e)) {
+	debug(31, 3) ("htcpCheckHit: NO; entry not valid to send\n");
+	goto miss;
+    }
+    if (refreshCheckHTCP(e, request)) {
 	debug(31, 3) ("htcpCheckHit: NO; cached response is stale\n");
-	e = NULL;
-    } else {
-	debug(31, 3) ("htcpCheckHit: YES!?\n");
+	goto miss;
     }
+    debug(31, 3) ("htcpCheckHit: YES!?\n");
+    hit = e;
+miss:
     requestDestroy(request);
-    return e;
+    return hit;
 }
 
 static void
Index: squid/src/http.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/http.c,v
retrieving revision 1.1.1.3.4.3
retrieving revision 1.1.1.3.4.3.4.1
diff -u -r1.1.1.3.4.3 -r1.1.1.3.4.3.4.1
--- squid/src/http.c	1 Jul 2000 12:05:14 -0000	1.1.1.3.4.3
+++ squid/src/http.c	18 Jan 2001 20:12:43 -0000	1.1.1.3.4.3.4.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: http.c,v 1.1.1.3.4.3 2000/07/01 12:05:14 hno Exp $
+ * $Id: http.c,v 1.1.1.3.4.3.4.1 2001/01/18 20:12:43 hno Exp $
  *
  * DEBUG: section 11    Hypertext Transfer Protocol (HTTP)
  * AUTHOR: Harvest Derived
@@ -168,7 +168,11 @@
     if (!remove && !forbidden)
 	return;
     assert(e->mem_obj);
-    if ((pe = storeGetPublic(e->mem_obj->url, e->mem_obj->method)) != NULL) {
+    if (e->mem_obj->request)
+	pe = storeGetPublicByRequest(e->mem_obj->request);
+    else
+    	pe = storeGetPublic(e->mem_obj->url, e->mem_obj->method);
+    if (pe != NULL) {
 	assert(e != pe);
 	storeRelease(pe);
     }
@@ -176,7 +180,11 @@
      * Also remove any cached HEAD response in case the object has
      * changed.
      */
-    if ((pe = storeGetPublic(e->mem_obj->url, METHOD_HEAD)) != NULL) {
+    if (e->mem_obj->request)
+	pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_HEAD);
+    else 
+	pe = storeGetPublic(e->mem_obj->url, METHOD_HEAD);
+    if (pe != NULL) {
 	assert(e != pe);
 	storeRelease(pe);
     }
@@ -194,7 +202,11 @@
 	 * Remove any cached GET object if it is beleived that the
 	 * object may have changed as a result of other methods
 	 */
-	if ((pe = storeGetPublic(e->mem_obj->url, METHOD_GET)) != NULL) {
+	if (e->mem_obj->request)
+	    pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_GET);
+	else 
+	    pe = storeGetPublic(e->mem_obj->url, METHOD_GET);
+	if (pe != NULL) {
 	    assert(e != pe);
 	    storeRelease(pe);
 	}
@@ -224,12 +236,6 @@
 	if (!EBIT_TEST(cc_mask, CC_PUBLIC))
 	    return 0;
     }
-    /*
-     * We don't properly deal with Vary features yet, so we can't
-     * cache these
-     */
-    if (httpHeaderHas(hdr, HDR_VARY))
-	return 0;
     /* Pragma: no-cache in _replies_ is not documented in HTTP,
      * but servers like "Active Imaging Webcast/2.0" sure do use it */
     if (httpHeaderHas(hdr, HDR_PRAGMA)) {
@@ -314,6 +320,49 @@
     /* NOTREACHED */
 }
 
+/*
+ * For Vary, store the relevant request headers as 
+ * virtual headers in the reply
+ * Returns false if the variance cannot be stored
+ */
+const char *
+httpMakeVaryMark(request_t * request, HttpReply *reply)
+{
+    int ok = 1;
+    String vary, hdr;
+    const char *pos = NULL;
+    const char *item;
+    const char *name;
+    const char *value;
+    int ilen;
+    http_hdr_type id;
+    static String vstr = {0,0,NULL};
+
+    stringClean(&vstr);
+    vary = httpHeaderGetList(&reply->header, HDR_VARY);
+    while (strListGetItem(&vary, ',', &item, &ilen, &pos)) {
+	id = httpHeaderIdByNameDef(item, ilen);
+	if (id == -1) {
+	    debug(11, 1) ("httpMakeVaryMark: Unknown vary header '%s'\n", item);
+	    return NULL;
+	}
+	hdr = httpHeaderGetStrOrList(&request->header, id);
+	name = httpHeaderNameById(id);
+	strListAdd(&vstr, name, ',');
+	value = strBuf(hdr);
+	if (value) {
+	    value = rfc1738_escape(value);
+	    stringAppend(&vstr, "=\"", 2);
+	    stringAppend(&vstr, value, strlen(value));
+	    stringAppend(&vstr, "\"", 1);
+	}
+	stringClean(&hdr);
+    }
+    debug(11, 3) ("httpMakeVaryMark: %d / %s\n", ok, strBuf(vstr));
+    stringClean(&vary);
+    return strBuf(vstr);
+}
+
 /* rewrite this later using new interfaces @?@ */
 void
 httpProcessReplyHeader(HttpStateData * httpState, const char *buf, int size)
@@ -364,7 +413,18 @@
 	httpMaybeRemovePublic(entry, reply->sline.status);
     switch (httpCachableReply(httpState)) {
     case 1:
-	httpMakePublic(entry);
+	if (httpHeaderHas(&reply->header, HDR_VARY)) {
+	    const char *vary = httpMakeVaryMark(httpState->request, reply);
+	    if (vary) {
+		entry->mem_obj->vary_headers = xstrdup(vary);
+		/* Kill the old base object if a change in variance is detected */
+		httpMakePublic(entry);
+	    } else {
+		httpMakePrivate(entry);
+	    }
+	} else {
+	    httpMakePublic(entry);
+	}
 	break;
     case 0:
 	httpMakePrivate(entry);
Index: squid/src/neighbors.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/neighbors.c,v
retrieving revision 1.1.1.3.4.1
retrieving revision 1.1.1.3.4.1.6.1
diff -u -r1.1.1.3.4.1 -r1.1.1.3.4.1.6.1
--- squid/src/neighbors.c	17 Apr 2000 00:56:53 -0000	1.1.1.3.4.1
+++ squid/src/neighbors.c	18 Jan 2001 20:12:43 -0000	1.1.1.3.4.1.6.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: neighbors.c,v 1.1.1.3.4.1 2000/04/17 00:56:53 hno Exp $
+ * $Id: neighbors.c,v 1.1.1.3.4.1.6.1 2001/01/18 20:12:43 hno Exp $
  *
  * DEBUG: section 15    Neighbor Routines
  * AUTHOR: Harvest Derived
@@ -522,10 +522,10 @@
 
 /* lookup the digest of a given peer */
 lookup_t
-peerDigestLookup(peer * p, request_t * request, StoreEntry * entry)
+peerDigestLookup(peer * p, request_t * request)
 {
 #if USE_CACHE_DIGESTS
-    const cache_key *key = request ? storeKeyPublic(storeUrl(entry), request->method) : NULL;
+    const cache_key *key = request ? storeKeyPublicByRequest(request) : NULL;
     assert(p);
     assert(request);
     debug(15, 5) ("peerDigestLookup: peer %s\n", p->host);
@@ -561,7 +561,7 @@
 
 /* select best peer based on cache digests */
 peer *
-neighborsDigestSelect(request_t * request, StoreEntry * entry)
+neighborsDigestSelect(request_t * request)
 {
     peer *best_p = NULL;
 #if USE_CACHE_DIGESTS
@@ -574,14 +574,14 @@
     int i;
     if (!request->flags.hierarchical)
 	return NULL;
-    key = storeKeyPublic(storeUrl(entry), request->method);
+    key = storeKeyPublicByRequest(request);
     for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
 	lookup_t lookup;
 	if (!p)
 	    p = Config.peers;
 	if (i == 1)
 	    first_ping = p;
-	lookup = peerDigestLookup(p, request, entry);
+	lookup = peerDigestLookup(p, request);
 	if (lookup == LOOKUP_NONE)
 	    continue;
 	choice_count++;
Index: squid/src/peer_digest.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/peer_digest.c,v
retrieving revision 1.1.1.3.4.1
retrieving revision 1.1.1.3.4.1.6.1
diff -u -r1.1.1.3.4.1 -r1.1.1.3.4.1.6.1
--- squid/src/peer_digest.c	17 Apr 2000 00:56:53 -0000	1.1.1.3.4.1
+++ squid/src/peer_digest.c	18 Jan 2001 20:12:43 -0000	1.1.1.3.4.1.6.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: peer_digest.c,v 1.1.1.3.4.1 2000/04/17 00:56:53 hno Exp $
+ * $Id: peer_digest.c,v 1.1.1.3.4.1.6.1 2001/01/18 20:12:43 hno Exp $
  *
  * DEBUG: section 72    Peer Digest Routines
  * AUTHOR: Alex Rousskov
@@ -281,10 +281,10 @@
 	url = internalRemoteUri(p->host, p->http_port,
 	    "/squid-internal-periodic/", StoreDigestFileName);
 
-    key = storeKeyPublic(url, METHOD_GET);
-    debug(72, 2) ("peerDigestRequest: %s key: %s\n", url, storeKeyText(key));
     req = urlParse(METHOD_GET, url);
     assert(req);
+    key = storeKeyPublicByRequest(req);
+    debug(72, 2) ("peerDigestRequest: %s key: %s\n", url, storeKeyText(key));
 
     /* add custom headers */
     assert(!req->header.len);
Index: squid/src/peer_select.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/peer_select.c,v
retrieving revision 1.1.1.3.4.1
retrieving revision 1.1.1.3.4.1.6.1
diff -u -r1.1.1.3.4.1 -r1.1.1.3.4.1.6.1
--- squid/src/peer_select.c	17 Apr 2000 00:56:53 -0000	1.1.1.3.4.1
+++ squid/src/peer_select.c	18 Jan 2001 20:12:43 -0000	1.1.1.3.4.1.6.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: peer_select.c,v 1.1.1.3.4.1 2000/04/17 00:56:53 hno Exp $
+ * $Id: peer_select.c,v 1.1.1.3.4.1.6.1 2001/01/18 20:12:43 hno Exp $
  *
  * DEBUG: section 44    Peer Selection Algorithm
  * AUTHOR: Duane Wessels
@@ -304,7 +304,7 @@
 	return;
     }
 #if USE_CACHE_DIGESTS
-    if ((p = neighborsDigestSelect(request, entry))) {
+    if ((p = neighborsDigestSelect(request))) {
 	if (neighborType(p, request) == PEER_PARENT)
 	    code = CD_PARENT_HIT;
 	else
Index: squid/src/protos.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/protos.h,v
retrieving revision 1.1.1.3.4.1
retrieving revision 1.1.1.3.4.1.6.1
diff -u -r1.1.1.3.4.1 -r1.1.1.3.4.1.6.1
--- squid/src/protos.h	17 Apr 2000 00:56:53 -0000	1.1.1.3.4.1
+++ squid/src/protos.h	18 Jan 2001 20:12:43 -0000	1.1.1.3.4.1.6.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: protos.h,v 1.1.1.3.4.1 2000/04/17 00:56:53 hno Exp $
+ * $Id: protos.h,v 1.1.1.3.4.1.6.1 2001/01/18 20:12:43 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -290,6 +290,7 @@
 extern int httpAnonHdrAllowed(http_hdr_type hdr_id);
 extern int httpAnonHdrDenied(http_hdr_type hdr_id);
 extern void httpBuildRequestHeader(request_t *, request_t *, StoreEntry *, HttpHeader *, int, http_state_flags);
+extern const char *httpMakeVaryMark(request_t *request, HttpReply *reply);
 
 /* ETag */
 extern int etagParseInit(ETag * etag, const char *str);
@@ -425,6 +426,7 @@
 extern const char *httpHeaderGetLastStr(const HttpHeader * hdr, http_hdr_type id);
 extern const char *httpHeaderGetAuth(const HttpHeader * hdr, http_hdr_type id, const char *authScheme);
 extern String httpHeaderGetList(const HttpHeader * hdr, http_hdr_type id);
+extern String httpHeaderGetStrOrList(const HttpHeader * hdr, http_hdr_type id);
 extern int httpHeaderDelByName(HttpHeader * hdr, const char *name);
 extern int httpHeaderDelById(HttpHeader * hdr, http_hdr_type id);
 extern void httpHeaderDelAt(HttpHeader * hdr, HttpHeaderPos pos);
@@ -628,8 +630,8 @@
 extern peer *getDefaultParent(request_t * request);
 extern peer *getRoundRobinParent(request_t * request);
 extern peer *getAnyParent(request_t * request);
-extern lookup_t peerDigestLookup(peer * p, request_t * request, StoreEntry * entry);
-extern peer *neighborsDigestSelect(request_t * request, StoreEntry * entry);
+extern lookup_t peerDigestLookup(peer * p, request_t * request);
+extern peer *neighborsDigestSelect(request_t * request);
 extern void peerNoteDigestLookup(request_t * request, peer * p, lookup_t lookup);
 extern void peerNoteDigestGone(peer * p);
 extern int neighborUp(const peer * e);
@@ -800,6 +802,8 @@
 extern StoreEntry *new_StoreEntry(int, const char *, const char *);
 extern StoreEntry *storeGet(const cache_key *);
 extern StoreEntry *storeGetPublic(const char *uri, const method_t method);
+extern StoreEntry *storeGetPublicByRequest(request_t *request);
+extern StoreEntry *storeGetPublicByRequestMethod(request_t *request, const method_t method);
 extern StoreEntry *storeCreateEntry(const char *, const char *, request_flags, method_t);
 extern void storeSetPublicKey(StoreEntry *);
 extern void storeComplete(StoreEntry *);
@@ -906,6 +910,8 @@
 extern const cache_key *storeKeyScan(const char *);
 extern const char *storeKeyText(const cache_key *);
 extern const cache_key *storeKeyPublic(const char *, const method_t);
+extern const cache_key *storeKeyPublicByRequest(request_t *);
+extern const cache_key *storeKeyPublicByRequestMethod(request_t *, const method_t);
 extern const cache_key *storeKeyPrivate(const char *, method_t, int);
 extern int storeKeyHashBuckets(int);
 extern int storeKeyNull(const cache_key *);
@@ -1214,3 +1220,6 @@
 extern int getpagesize(void);
 extern int gethostname(char *, int);
 #endif
+
+/* Vary support functions */
+int varyEvaluateMatch(StoreEntry *entry, request_t *req); 
Index: squid/src/store.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store.c,v
retrieving revision 1.1.1.3.4.5
retrieving revision 1.1.1.3.4.5.4.1
diff -u -r1.1.1.3.4.5 -r1.1.1.3.4.5.4.1
--- squid/src/store.c	1 Aug 2000 00:14:35 -0000	1.1.1.3.4.5
+++ squid/src/store.c	18 Jan 2001 20:12:43 -0000	1.1.1.3.4.5.4.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store.c,v 1.1.1.3.4.5 2000/08/01 00:14:35 hno Exp $
+ * $Id: store.c,v 1.1.1.3.4.5.4.1 2001/01/18 20:12:43 hno Exp $
  *
  * DEBUG: section 20    Storage Manager
  * AUTHOR: Harvest Derived
@@ -157,6 +157,7 @@
     ctx_exit(ctx);		/* must exit before we free mem->url */
     safe_free(mem->url);
     safe_free(mem->log_url);	/* XXX account log_url */
+    safe_free((void *)mem->vary_headers);
     memFree(mem, MEM_MEMOBJECT);
 }
 
@@ -324,6 +325,22 @@
     return storeGet(storeKeyPublic(uri, method));
 }
 
+StoreEntry *
+storeGetPublicByRequestMethod(request_t *req, const method_t method)
+{
+    return storeGet(storeKeyPublicByRequestMethod(req, method));
+}
+
+StoreEntry *
+storeGetPublicByRequest(request_t *req)
+{
+    StoreEntry *e = storeGetPublicByRequestMethod(req, req->method);
+    if (e == NULL && req->method == METHOD_HEAD)
+	/* We can generate a HEAD reply from a cached GET object */
+	e = storeGetPublicByRequestMethod(req, METHOD_GET);
+    return e;
+}
+
 static int
 getKeyCounter(void)
 {
@@ -381,12 +398,55 @@
 	    e->key, mem->url);
 #endif
     assert(!EBIT_TEST(e->flags, RELEASE_REQUEST));
-    newkey = storeKeyPublic(mem->url, mem->method);
+    if (mem->request) {
+	StoreEntry *pe;
+	request_t *request = mem->request;
+	if (!mem->vary_headers) {
+	    /* First handle the case where the object no longer varies */
+	    safe_free(request->vary_headers);
+	} else {
+	    if (request->vary_headers && strcmp(request->vary_headers, mem->vary_headers) != 0) {
+		/* Oops.. the variance has changed. Kill the base object
+		 * to record the new variance key
+		 */
+		safe_free(request->vary_headers); /* free old "bad" variance key */
+		pe = storeGetPublic(mem->url, mem->method);
+		if (pe)
+		    storeRelease(pe);
+	    }
+	    /* Make sure the request knows the variance status */
+	    if (!request->vary_headers)
+		request->vary_headers = xstrdup(httpMakeVaryMark(request, mem->reply));
+	}
+	if (mem->vary_headers && !storeGetPublic(mem->url, mem->method)) {
+	    /* Create "vary" base object */
+	    http_version_t version;
+	    String vary;
+	    pe = storeCreateEntry(mem->url, mem->log_url, request->flags, request->method);
+	    httpBuildVersion(&version, 1, 0);
+	    httpReplySetHeaders(pe->mem_obj->reply, version, HTTP_OK, "Internal marker object", "x-squid-internal/vary", -1, -1, squid_curtime + 100000);
+	    vary = httpHeaderGetList(&mem->reply->header, HDR_VARY);
+	    httpHeaderPutStr(&pe->mem_obj->reply->header, HDR_VARY, strBuf(vary));
+	    stringClean(&vary);
+	    storeSetPublicKey(pe);
+	    httpReplySwapOut(pe->mem_obj->reply, pe);
+	    storeBufferFlush(pe);
+	    storeTimestampsSet(pe);
+	    storeComplete(pe);
+	    storeUnlockObject(pe);
+	}
+	newkey = storeKeyPublicByRequest(mem->request);
+    }
+    else
+	newkey = storeKeyPublic(mem->url, mem->method);
     if ((e2 = (StoreEntry *) hash_lookup(store_table, newkey))) {
 	debug(20, 3) ("storeSetPublicKey: Making old '%s' private.\n", mem->url);
 	storeSetPrivateKey(e2);
 	storeRelease(e2);
-	newkey = storeKeyPublic(mem->url, mem->method);
+	if (mem->request)
+	    newkey = storeKeyPublicByRequest(mem->request);
+	else
+	    newkey = storeKeyPublic(mem->url, mem->method);
     }
     if (e->key)
 	storeHashDelete(e);
Index: squid/src/store_client.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_client.c,v
retrieving revision 1.1.1.3.4.2
retrieving revision 1.1.1.3.4.2.6.1
diff -u -r1.1.1.3.4.2 -r1.1.1.3.4.2.6.1
--- squid/src/store_client.c	17 Apr 2000 00:56:53 -0000	1.1.1.3.4.2
+++ squid/src/store_client.c	18 Jan 2001 20:12:43 -0000	1.1.1.3.4.2.6.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_client.c,v 1.1.1.3.4.2 2000/04/17 00:56:53 hno Exp $
+ * $Id: store_client.c,v 1.1.1.3.4.2.6.1 2001/01/18 20:12:43 hno Exp $
  *
  * DEBUG: section 20    Storage Manager Client-Side Interface
  * AUTHOR: Duane Wessels
@@ -389,6 +389,15 @@
 	    break;
 	case STORE_META_STD:
 	    break;
+	case STORE_META_VARY_HEADERS:
+	    if (mem->vary_headers) {
+		if (strcmp(mem->vary_headers, t->value) != 0)
+		    swap_object_ok = 0;
+	    } else {
+		/* Assume the object is OK.. remember the vary request headers */
+		mem->vary_headers = xstrdup(t->value);
+	    }
+	    break;
 	default:
 	    debug(20, 1) ("WARNING: got unused STORE_META type %d\n", t->type);
 	    break;
Index: squid/src/store_key_md5.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_key_md5.c,v
retrieving revision 1.1.1.3.4.1
retrieving revision 1.1.1.3.4.1.6.1
diff -u -r1.1.1.3.4.1 -r1.1.1.3.4.1.6.1
--- squid/src/store_key_md5.c	17 Apr 2000 00:56:53 -0000	1.1.1.3.4.1
+++ squid/src/store_key_md5.c	18 Jan 2001 20:12:43 -0000	1.1.1.3.4.1.6.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_key_md5.c,v 1.1.1.3.4.1 2000/04/17 00:56:53 hno Exp $
+ * $Id: store_key_md5.c,v 1.1.1.3.4.1.6.1 2001/01/18 20:12:43 hno Exp $
  *
  * DEBUG: section 20    Storage Manager MD5 Cache Keys
  * AUTHOR: Duane Wessels
@@ -121,6 +121,28 @@
 }
 
 const cache_key *
+storeKeyPublicByRequest(request_t *request)
+{
+    return storeKeyPublicByRequestMethod(request, request->method);
+}
+
+const cache_key *
+storeKeyPublicByRequestMethod(request_t *request, const method_t method)
+{
+    static cache_key digest[MD5_DIGEST_CHARS];
+    unsigned char m = (unsigned char) method;
+    const char *url = urlCanonical(request);
+    MD5_CTX M;
+    MD5Init(&M);
+    MD5Update(&M, &m, sizeof(m));
+    MD5Update(&M, (unsigned char *) url, strlen(url));
+    if (request->vary_headers)
+	MD5Update(&M, (unsigned char *) request->vary_headers, strlen(request->vary_headers));
+    MD5Final(digest, &M);
+    return digest;
+}
+
+cache_key *
 storeKeyDup(const cache_key * key)
 {
     cache_key *dup = memAllocate(MEM_MD5_DIGEST);
Index: squid/src/store_swapmeta.c
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/store_swapmeta.c,v
retrieving revision 1.1.1.2.4.2
retrieving revision 1.1.1.2.4.2.4.1
diff -u -r1.1.1.2.4.2 -r1.1.1.2.4.2.4.1
--- squid/src/store_swapmeta.c	1 Aug 2000 00:05:19 -0000	1.1.1.2.4.2
+++ squid/src/store_swapmeta.c	18 Jan 2001 20:12:43 -0000	1.1.1.2.4.2.4.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: store_swapmeta.c,v 1.1.1.2.4.2 2000/08/01 00:05:19 hno Exp $
+ * $Id: store_swapmeta.c,v 1.1.1.2.4.2.4.1 2001/01/18 20:12:43 hno Exp $
  *
  * DEBUG: section 20    Storage Manager Swapfile Metadata
  * AUTHOR: Kostas Anagnostakis
@@ -68,6 +68,8 @@
     tlv *TLV = NULL;		/* we'll return this */
     tlv **T = &TLV;
     const char *url;
+    const char *vary;
+
     assert(mem != NULL);
     assert(e->swap_status == SWAPOUT_WRITING);
     url = storeUrl(e);
@@ -75,6 +77,9 @@
     T = storeSwapTLVAdd(STORE_META_KEY, e->key, MD5_DIGEST_CHARS, T);
     T = storeSwapTLVAdd(STORE_META_STD, &e->timestamp, STORE_HDR_METASIZE, T);
     T = storeSwapTLVAdd(STORE_META_URL, url, strlen(url) + 1, T);
+    vary = e->mem_obj->vary_headers;
+    if (vary)
+	T = storeSwapTLVAdd(STORE_META_VARY_HEADERS, vary, strlen(vary) + 1, T);
     return TLV;
 }
 
Index: squid/src/structs.h
===================================================================
RCS file: /cvsroot/squid-sf//squid/src/structs.h,v
retrieving revision 1.1.1.3.4.2
retrieving revision 1.1.1.3.4.2.6.1
diff -u -r1.1.1.3.4.2 -r1.1.1.3.4.2.6.1
--- squid/src/structs.h	17 Apr 2000 00:56:54 -0000	1.1.1.3.4.2
+++ squid/src/structs.h	18 Jan 2001 20:12:43 -0000	1.1.1.3.4.2.6.1
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.1.1.3.4.2 2000/04/17 00:56:54 hno Exp $
+ * $Id: structs.h,v 1.1.1.3.4.2.6.1 2001/01/18 20:12:43 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -417,6 +417,7 @@
 #if USE_CACHE_DIGESTS
 	int digest_generation;
 #endif
+	int vary_ignore_expire;
     } onoff;
     acl *aclList;
     struct {
@@ -872,6 +873,7 @@
 	unsigned int accel:1;
 	unsigned int internal:1;
 	unsigned int done_copying:1;
+	unsigned int purging:1;
     } flags;
     struct {
 	http_status status;
@@ -1292,6 +1294,7 @@
     int id;
     ssize_t object_sz;
     size_t swap_hdr_sz;
+    const char *vary_headers;
 };
 
 struct _StoreEntry {
@@ -1452,6 +1455,7 @@
     err_type err_type;
     char *peer_login;		/* Configured peer login:password */
     time_t lastmod;		/* Used on refreshes */
+    char *vary_headers;		/* Used when varying entities are detected. Changes how the store key is calculated */
 };
 
 struct _cachemgr_passwd {
