trafficserver
trafficserver copied to clipboard
fix: properly process If-Range headers in client requests
Problem
ATS doesn't respond correctly to conditional range requests. According to the spec, ATS must ignore the Range header and send back the full content when the condition in the If-Range header isn't satisified. ATS responds with 416 Requested Range Not Satisfiable instead.
How to reproduce
- Prepare a cacheable HTTP endpoint for ATS (e.g., http://localhost/)
- Launch ATS
- Send a normal request for the entire content so that it'd be cached in ATS (e.g.,
curl -vv http://localhost) - Send a conditional range request for the cached content. Specify a weak etag so that it'd fail to meet the requirements needed to receive a partial response. (e.g.,
curl -vv -H 'If-Range: W/"this_wont_match"' http://localhost)
Cause
ATS validates If-Range headers in match_response_to_request_conditionals(). If the condition specified in If-Range isn't met, match_response_to_request_conditionals() returns a response code of HTTP_STATUS_RANGE_NOT_SATISFIABLE. However, ATS can't determine whether a HTTP_STATUS_RANGE_NOT_SATISFIABLE response code came from match_response_to_request_conditionals() or the response of the original content. This confusion led ATS to return incorrect responses to conditional range requests.
Changes made
- Move the
If-Rangeheader validation code out ofmatch_response_to_request_conditionals()so that it would run right before processing theRangeheader. This makes it easier to determine the correct response. - Add autest test cases to check how ATS responds to range requests.
@ezelkow1 can you kick off ci for this pr?
[approve ci]
Looks good overall. Excellent description!
I've been trying to recreate the issue and I just ran the autests in this PR against master without this PR and they all pass. Did some other PR already fix this?
I tried reproducing this again, and it looks like the reproduction steps were insufficient. It looks like I need to set proxy.config.http.cache.range.write to 1 to reproduce. I'm working on an autest fix.
[approve ci autest]
#8657 might've affected the test result, assuming that the CI does a merge with the current master branch before running the them. I'll try rebasing this PR.
Anything new on this PR?
Sorry for the delay. I've rebased and tweaked the changes against the master branch.
It turns out #8657 did change a few things, but the same issue still persists. Now instead of HTTP_STATUS_RANGE_NOT_SATISFIABLE, it responds with HTTP_STATUS_PARTIAL_CONTENT when it should be giving the whole response. And while the pre-#8657 code gave an incorrect response regardless of the content of the If-Range header, the current code only responds incorrectly when given an non-matching If-Range condition.