[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