Commit fed96be0 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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)
parent 53cc8318
......@@ -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 *,
......
......@@ -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);
......
......@@ -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);
/*
......
......@@ -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 */
......
......@@ -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);
}
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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment