[master] fed96be Weaken the Etag whenever processing means that we do not deliver the exact same byte sequence from the backend, Gzip, Gunzip or ESI expansion.

Poul-Henning Kamp phk at varnish-cache.org
Mon Nov 18 21:21:04 CET 2013


commit fed96be07b7d7bcc29ef46bb76001431e6ec80ff
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Nov 18 20:14:57 2013 +0000

    Weaken the Etag whenever processing means that we do not deliver
    the exact same byte sequence from the backend, Gzip, Gunzip or ESI
    expansion.
    
    (See also: #940)

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index a4a8e99..5ed30c4 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -1206,6 +1206,8 @@ void RFC2616_Ttl(struct busyobj *);
 enum body_status RFC2616_Body(struct busyobj *, struct dstat *);
 unsigned RFC2616_Req_Gzip(const struct http *);
 int RFC2616_Do_Cond(const struct req *sp);
+void RFC2616_Weaken_Etag(struct http *hp);
+
 
 /* stevedore.c */
 struct object *STV_NewObject(struct busyobj *,
diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index ce74d35..914217e 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -308,14 +308,24 @@ vbf_stp_fetch(struct worker *wrk, struct busyobj *bo)
 	assert(bo->do_gzip == 0 || bo->do_gunzip == 0);
 
 	/* ESI takes precedence and handles gzip/gunzip itself */
-	if (bo->do_esi)
+	if (bo->do_esi) {
 		bo->vfp = &vfp_esi;
-	else if (bo->do_gunzip)
+		/*
+		 * The one case were we do not weaken Etag is where
+		 * incoming obj is not gzip'ed and we don't gzip either
+		 * If we ESI expand it on deliver, we weaken there.
+		 */
+		if (bo->is_gzip || bo->do_gzip | bo->do_gunzip)
+			RFC2616_Weaken_Etag(bo->beresp);
+	} else if (bo->do_gunzip) {
 		bo->vfp = &vfp_gunzip;
-	else if (bo->do_gzip)
+		RFC2616_Weaken_Etag(bo->beresp);
+	} else if (bo->do_gzip) {
 		bo->vfp = &vfp_gzip;
-	else if (bo->is_gzip)
+		RFC2616_Weaken_Etag(bo->beresp);
+	} else if (bo->is_gzip) {
 		bo->vfp = &vfp_testgzip;
+	}
 
 	if (bo->fetch_objcore->flags & OC_F_PRIVATE)
 		AN(bo->uncacheable);
diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c
index baf33d5..dc78078 100644
--- a/bin/varnishd/cache/cache_http1_deliver.c
+++ b/bin/varnishd/cache/cache_http1_deliver.c
@@ -261,6 +261,9 @@ V1D_Deliver(struct req *req)
 			v1d_dorange(req, r);
 	}
 
+	if (req->res_mode & RES_ESI)
+		RFC2616_Weaken_Etag(req->resp);
+
 	WRW_Reserve(req->wrk, &req->sp->fd, req->vsl, req->t_resp);
 
 	/*
diff --git a/bin/varnishd/cache/cache_req_fsm.c b/bin/varnishd/cache/cache_req_fsm.c
index bab3b61..5502a4b 100644
--- a/bin/varnishd/cache/cache_req_fsm.c
+++ b/bin/varnishd/cache/cache_req_fsm.c
@@ -129,6 +129,10 @@ cnt_deliver(struct worker *wrk, struct req *req)
 
 	http_SetHeader(req->resp, "Via: 1.1 varnish");
 
+	if (cache_param->http_gzip_support && req->obj->gziped &&
+	    !RFC2616_Req_Gzip(req->http))
+		RFC2616_Weaken_Etag(req->resp);
+
 	VCL_deliver_method(req->vcl, wrk, req, NULL, req->http->ws);
 
 	/* Stop the insanity before it turns "Hotel California" on us */
diff --git a/bin/varnishd/cache/cache_rfc2616.c b/bin/varnishd/cache/cache_rfc2616.c
index 66724ab..4bd45ca 100644
--- a/bin/varnishd/cache/cache_rfc2616.c
+++ b/bin/varnishd/cache/cache_rfc2616.c
@@ -346,3 +346,21 @@ RFC2616_Do_Cond(const struct req *req)
 
 	return (do_cond);
 }
+
+/*--------------------------------------------------------------------*/
+
+void
+RFC2616_Weaken_Etag(struct http *hp)
+{
+	char *p;
+
+	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
+
+	if (!http_GetHdr(hp, H_ETag, &p))
+		return;
+	AN(p);
+	if (p[0] == 'W' && p[1] == '/')
+		return;
+	http_Unset(hp, H_ETag);
+	http_PrintfHeader(hp, "ETag: W/%s", p);
+}
diff --git a/bin/varnishtest/tests/r00940.vtc b/bin/varnishtest/tests/r00940.vtc
new file mode 100644
index 0000000..0d41b38
--- /dev/null
+++ b/bin/varnishtest/tests/r00940.vtc
@@ -0,0 +1,96 @@
+varnishtest "GZIP, ESI and etags"
+
+server s1 {
+	rxreq
+	expect req.url == /1
+	expect req.http.accept-encoding == "gzip"
+	txresp -hdr {ETag: "foo"}  -gziplen 41
+
+	rxreq
+	expect req.url == /2
+	txresp -hdr {ETag: "foo2"}  -bodylen 42
+
+	rxreq
+	expect req.url == /3
+	txresp -hdr {ETag: "foo3"}  -body {<H1><esi:remove> foo </esi:remove><H2>}
+
+	rxreq
+	expect req.url == /4
+	txresp -hdr {ETag: "foo4"}  -gzipbody {<H11><esi:remove> foo </esi:remove><H22>}
+} -start
+
+varnish v1 -vcl+backend { 
+	sub vcl_backend_response {
+		if (bereq.url == "/2") {
+			set beresp.do_gzip = true;
+		}
+		if (bereq.url == "/3" || bereq.url == "/4") {
+			set beresp.do_esi = true;
+		}
+	}
+	sub vcl_deliver {
+		if (req.http.foo == "noesi") {
+			set req.esi = false;
+		}
+	}
+} -start
+
+client c1 {
+	# Straight through gzip, strong etag survives
+	txreq -url /1 -hdr "Accept-Encoding: gzip"
+	rxresp
+	expect resp.http.etag == {"foo"}
+	gunzip
+	expect resp.bodylen == 41
+
+	delay .2
+
+	# gzip in, gunzip out, weak etag
+	txreq -url /1
+	rxresp
+	expect resp.http.etag == {W/"foo"}
+	expect resp.bodylen == 41
+
+	delay .2
+
+	# Gzip on input, weak etag
+	txreq -url /2 -hdr "Accept-Encoding: gzip"
+	rxresp
+	expect resp.http.etag == {W/"foo2"}
+	gunzip
+	expect resp.bodylen == 42
+
+	delay .2
+
+	# Gzip on input, gunzip on output, weak etag
+	txreq -url /2
+	rxresp
+	expect resp.http.etag == {W/"foo2"}
+	expect resp.bodylen == 42
+
+	delay .2
+
+	# ESI expansion, weak etag
+	txreq -url /3
+	rxresp
+	expect resp.http.etag == {W/"foo3"}
+	expect resp.bodylen == 8
+
+	delay .2
+
+	# ESI parse, but no expansion, strong etag
+	txreq -url /3 -hdr "foo: noesi"
+	rxresp
+	expect resp.http.etag == {"foo3"}
+	expect resp.bodylen == 38
+
+	delay .2
+
+	# ESI parse, no expansion, but re-gzipping, weak etag
+	txreq -url /4 -hdr "foo: noesi" -hdr "Accept-Encoding: gzip"
+	rxresp
+	expect resp.http.etag == {W/"foo4"}
+	gunzip
+	expect resp.bodylen == 40
+
+} -run



More information about the varnish-commit mailing list