resp.do_esi is undefined after setting resp.filters

After fixing resp.filters, resp.do_esi loses its meaning.

Note:

Setting resp.filters also fixes whether or not the gunzip and range VDPs
are being pushed.

These do not depend on switches, but on request headers. So we need to
consider the case that a VCL author

	- fixes resp.filters
	- and then adds or removes relevant headers

* req.http.Accept-Encoding for the gunzip vdp

  if removed: gunzip stays in the VDP list, which is always ok

  if added: that is probably wrong anyway and the VCL author can
  be held responsible for their actions as per the warning in the
  resp.filters documentation.

* req.http.Range for the range vdp

  if removed: the range vdp vetoes itself in the _init callback

  if added: no range handling will be present, which is always ok
  (and see above for VCL author responsibilities)

Fixes #3002
parent ad176224
......@@ -869,6 +869,15 @@ VRT_r_resp_is_streaming(VRT_CTX)
/*--------------------------------------------------------------------*/
static inline int
resp_filter_fixed(VRT_CTX, const char *s)
{
if (ctx->req->filter_list == NULL)
return (0);
VRT_fail(ctx, "resp.filters are already fixed, %s is undefined", s);
return (1);
}
VCL_VOID
VRT_l_resp_do_esi(VRT_CTX, VCL_BOOL process_esi)
{
......@@ -876,6 +885,8 @@ VRT_l_resp_do_esi(VRT_CTX, VCL_BOOL process_esi)
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
assert(ctx->syntax >= 41);
if (resp_filter_fixed(ctx, "resp.do_esi"))
return;
ctx->req->disable_esi = !process_esi;
}
......@@ -886,6 +897,8 @@ VRT_r_resp_do_esi(VRT_CTX)
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
assert(ctx->syntax >= 41);
if (resp_filter_fixed(ctx, "resp.do_esi"))
return (0);
return (!ctx->req->disable_esi);
}
......
......@@ -71,10 +71,15 @@ server s1 {
varnish v1 -syntax 4.1 -vcl+backend {
sub vcl_deliver {
set resp.http.was = resp.do_esi;
set resp.http.filter0 = resp.filters;
if (req.url == "/top2") {
set resp.do_esi = false;
}
set resp.http.filters = resp.filters;
if (req.http.fiddle) {
set resp.filters = resp.filters;
set resp.do_esi = false;
}
}
sub vcl_backend_response {
set beresp.do_esi = true;
......@@ -89,6 +94,7 @@ client c1 {
expect resp.bodylen == 73
expect resp.status == 200
expect resp.http.was == true
expect resp.http.filter0 == "esi gunzip"
expect resp.http.filters == "gunzip"
txreq -url "/esi"
......@@ -96,6 +102,7 @@ client c1 {
expect resp.bodylen == 76
expect resp.status == 200
expect resp.http.was == true
expect resp.http.filter0 == "esi"
expect resp.http.filters == "esi"
# see Note on Range above
......@@ -120,6 +127,10 @@ client c1 {
expect resp.status == 200
expect resp.http.was == true
expect resp.http.filters == "esi gunzip range"
txreq -url /top2 -hdr "fiddle: do_esi"
rxresp
expect resp.status == 503
} -run
varnish v1 -expect esi_errors == 0
......@@ -1218,6 +1218,8 @@ resp.http.*
The HTTP headers that will be returned.
.. XXX does vcl_synth make any sense?
resp.do_esi ``VCL >= 4.1``
Type: BOOL
......@@ -1226,12 +1228,14 @@ resp.do_esi ``VCL >= 4.1``
Writable from: vcl_deliver, vcl_synth
Default: Set if ESI parsing has happened.
Default: obj.can_esi
This can be used to selectively disable ESI processing,
even though ESI parsing happened during fetch.
This is useful when Varnish caches peer with each other.
It is a VCL error to use resp.do_esi after setting resp.filters.
resp.is_streaming
......@@ -1252,6 +1256,15 @@ resp.filters
List of VDP filters the resp.body will be pushed through.
Before resp.filters is set, the value read will be the default
filter list as determined by varnish based on resp.do_esi and
request headers.
After resp.filters is set, changing any of the conditions
which otherwise determine the filter selection will have no
effiect. Using resp.do_esi is an error once resp.filters is
set.
Special variables
~~~~~~~~~~~~~~~~~
......
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