@@ -70,6 +70,107 @@ This granularity, and the general goal of the built-in subroutines split
7070is to allow to circumvent a specific aspect of the default rules without
7171giving the entire logic up.
7272
73+ Specific split built-in subroutines
74+ -----------------------------------
75+
76+ Some split subroutines in the built-in VCL deserve additional explanations:
77+
78+ .. _vcl-built-in-refresh :
79+
80+ vcl_refresh_*
81+ ~~~~~~~~~~~~~
82+
83+ These subroutines handle edge cases of backend refreshes. The precondition for
84+ these to be entered implicitly or explicitly via ``vcl_backend_refresh `` is that
85+ the current backend request can potentially create a cache object (that is, it
86+ is not for a private object as created by a pass or hit-for-pass) and that a
87+ stale object was found in cache which is not already invalidated. If this is the
88+ case, core code constructs a conditional ``GET `` request with the
89+ ``If-Modified-Since `` and/or ``If-None-Match `` headers set before
90+ ``vcl_backend_fetch `` is entered. If the VCL code does not remove the headers,
91+ the backend might respond with a ``304 Not Modified `` status, in which case
92+ ``vcl_backend_refresh `` is called on the response to decide what do do (see
93+ :ref: `vcl_backend_refresh ` for reference) and, if the built-in VCL is reached,
94+ the subs documented below will be called via ``vcl_builtin_backend_refresh ``.
95+
96+ vcl_refresh_valid
97+ ~~~~~~~~~~~~~~~~~
98+
99+ ``vcl_refresh_valid `` handles the case where the stale object to be revalidated
100+ by the 304 response got explicitly removed from the cache by a ban or purge
101+ while the backend request was in progress::
102+
103+ sub vcl_refresh_valid {
104+ if (!obj_stale.is_valid) {
105+ return (error(503, "Invalid object for refresh"));
106+ }
107+ }
108+
109+ The error is generated because alternative actions might require additional
110+ consideration. There are basically two options:
111+
112+ We can ignore the fact that the now successfully revalidated object was *just *
113+ invalidated by not falling through to the built-in VCL with this subroutine in
114+ the user VCL::
115+
116+ sub vcl_refresh_valid {
117+ return;
118+ }
119+
120+ This avoids the error but can potentially result in invalidations being
121+ ineffective.
122+
123+ The other option is to retry the backend request without the conditional request
124+ headers. This option is implicitly active whenever the user VCL results in a
125+ ``return(retry) `` from ``vcl_backend_error ``, because core code removes the
126+ conditional request headers if the stale object is found to be invalidated.
127+
128+ A variant of this option is an explicit retry for the case at hand::
129+
130+ sub vcl_refresh_valid {
131+ return (retry);
132+ }
133+
134+ To summarize, refreshes should work fine as long as there is at least one retry
135+ from ``vcl_backend_error `` for 503 errors. Additionally, VCL allows for
136+ customization if needed.
137+
138+ vcl_refresh_conditions
139+ ~~~~~~~~~~~~~~~~~~~~~~
140+
141+ This sub safeguards against invalid 304 responses getting unnoticed::
142+
143+ sub vcl_refresh_conditions {
144+ if (!bereq.http.if-modified-since &&
145+ !bereq.http.if-none-match) {
146+ return (error(503, "Unexpected 304"));
147+ }
148+ }
149+
150+ A backend should not respond with a 304 if neither of the conditional request
151+ headers were present in the backend request.
152+
153+ vcl_refresh_status
154+ ~~~~~~~~~~~~~~~~~~
155+
156+ This sub safeguards against accidental 304 responses if the stale object does
157+ not have a 200 status::
158+
159+ sub vcl_refresh_status {
160+ if (obj_stale.status != 200) {
161+ return (error(503, "Invalid object for refresh (status)"));
162+ }
163+ }
164+
165+ The background here is that the HTTP standards only allow refreshes of status
166+ 200 objects, but Vinyl Cache core code allows to deliberately violate this. In
167+ such cases, the status check needs to be neutered by not running the built-in
168+ code using::
169+
170+ sub vcl_refresh_status {
171+ return;
172+ }
173+
73174Built-in VCL reference
74175----------------------
75176
0 commit comments