backend-304 magic header merge in backend_response

Martin Gaitzsch martin at uplex.de
Thu Oct 10 10:19:22 UTC 2019


Good morning!

Yesterday I spent quite a while to understand the following behavior of
varnish (simplified):

first request
-------------
hash, backend response 200, no cache-control, cacheable, ttl 2m, 6h
grace and set "Cache-Control: no-cache" to make the client return to varnish

<...2m ttl passes...>

another request
---------------
triggers bg_fetch because of grace
backend response 304, again no cache-control from backend
BUT: the "OBJ".http.Cache-Control is merged to the response! So in
backend_response beresp.http.Cache-Control is "no-cache" - which is not
intuitive and also triggers code like this in backend_response (also see
builitin.vcl):

	if (!beresp.http.Surrogate-Control && beresp.http.Cache-Control ~
"(?i:no-cache|no-store|private)") {
		# Mark as "Hit-For-Miss" for the next 2 minutes
		set beresp.ttl = 120s;
		set beresp.uncacheable = true;
		return (deliver);
	}

...and that's not what I intended because my very useful grace-object
gets lost! (which we need during deployment 'downtimes')

Putting (! beresp.was_304) around the if-statement is not a solution
because this will fail in other situations. Valid workarounds are:

1. deleting Cache-Control in backend_response and only set it in deliver
downsides:
  - split "object preparation code" to backend_response and deliver,
which make vcl more complex than needed
  - needs to be done on every single response again instead of once in
backend_response

or
2. saving the original Cache-Control to an additional header and do
additional evaluations based on this header
downsides:
  - need to delete this header again in deliver on every response
  - real backend response headers of the current response still not
available for decisions; the merged headers are not sufficient to
conclude to the real backend response headers


Both options are not very appealing to me. How about giving access to
obj.* in backend_response and putting the real backend response headers
to beresp.* like the name indicates? This would be a clean transparent
and more intuitive solution which does not need header merge-magic.

Best
Martin


More information about the varnish-dev mailing list