-
Notifications
You must be signed in to change notification settings - Fork 381
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cache_req_fsm: keep the cache object's Content-Length for HEAD always #4247
Open
nigoroll
wants to merge
1
commit into
varnishcache:master
Choose a base branch
from
nigoroll:4245_head_cl
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+82
−8
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
varnishtest "cache a HEAD as a fallback for a GET" | ||
|
||
server s1 { | ||
rxreq | ||
expect req.method == "HEAD" | ||
expect req.http.t == "headmiss" | ||
txresp -nolen -hdr "Content-Length: 42" | ||
|
||
rxreq | ||
expect req.method == "GET" | ||
expect req.http.t == "getmiss" | ||
txresp -bodylen 42 | ||
} -start | ||
|
||
varnish v1 -vcl+backend { | ||
sub vcl_recv { | ||
if (req.method == "HEAD") { | ||
set req.http.X-Fetch-Method = "HEAD"; | ||
} else { | ||
unset req.http.X-Fetch-Method; | ||
} | ||
} | ||
|
||
sub vcl_backend_fetch { | ||
if (bereq.http.X-Fetch-Method) { | ||
set bereq.method = bereq.http.X-Fetch-Method; | ||
} | ||
} | ||
|
||
sub vcl_backend_response { | ||
# NOTE: this use of Vary is specific to this case, it is | ||
# usually WRONG to only set Vary for a specific condition | ||
if (bereq.http.X-Fetch-Method) { | ||
if (beresp.http.Vary) { | ||
set beresp.http.Vary += ", X-Fetch-Method"; | ||
} else { | ||
set beresp.http.Vary = "X-Fetch-Method"; | ||
} | ||
} | ||
set beresp.http.t = bereq.http.t; | ||
} | ||
|
||
sub vcl_deliver { | ||
# Vary cleanup | ||
if (resp.http.Vary == "X-Fetch-Method") { | ||
unset resp.http.Vary; | ||
} else if (resp.http.Vary ~ ", X-Fetch-Method$") { | ||
set resp.http.Vary = | ||
regsub(resp.http.Vary, ", X-Fetch-Method$", ""); | ||
} | ||
} | ||
} -start | ||
|
||
client c1 { | ||
# miss | ||
txreq -method "HEAD" -hdr "t: headmiss" | ||
rxresphdrs | ||
expect resp.http.t == "headmiss" | ||
# hit | ||
txreq -method "HEAD" -hdr "t: headhit" | ||
rxresphdrs | ||
expect resp.http.t == "headmiss" | ||
|
||
# miss | ||
txreq -hdr "t: getmiss" | ||
rxresp | ||
expect resp.http.t == "getmiss" | ||
# hits on full object | ||
txreq -hdr "t: gethit" | ||
rxresp | ||
expect resp.http.t == "getmiss" | ||
txreq -method "HEAD" -hdr "t: getheadhit" | ||
rxresphdrs | ||
expect resp.http.t == "getmiss" | ||
} -run | ||
|
||
server s1 -wait |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this example configuration, the
X-Fetch-Method
headers can't be unset here before sending the request to the backend or it breaks theVary
part, right? I don't mind sending an extra header to my backend but it's one thing that differs from therestart
-based solution.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. We need to (un)set the header before the cache lookup such that the right variant gets hit, if present. For a miss, the header gets copied to the backend request and, when it completes (after
vcl_backend_response {}
returns), the header's value gets added to the Vary specification for that cache object.So, in short, the header needs to be present during cache lookup and at the end of
vcl_backend_response {}
. For practical reasons, it is also needed to signal the backend side to activate theVary
handling.With these requirements in mind, we can change the code to not send the header by deleting it in
vcl_backend_fetch {}
and restoring it invcl_backend_response {}
, but we need a vmod to do so. Here's how the test case adjustment looks like with ataskvar.bool
object as a simple marker to activate the vary handling:For the purpose within the varnish-cache tree, we only use bundled vmods, so this change can not be applied to the proposed patch.
An even simpler way would be to use
bereq.method == "HEAD"
as the marker invcl_backend_response {}
, which should be possible if the additional logic is only used forHEAD
. That is, it should work exactly as in the test case, but might cause trouble in real world VCL: