Skip to content

Conversation

@midchildan
Copy link
Contributor

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

  1. Prepare a cacheable HTTP endpoint for ATS (e.g., http://localhost/)
  2. Launch ATS
  3. Send a normal request for the entire content so that it'd be cached in ATS (e.g., curl -vv http://localhost)
  4. 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-Range header validation code out of match_response_to_request_conditionals() so that it would run right before processing the Range header. This makes it easier to determine the correct response.
  • Add autest test cases to check how ATS responds to range requests.

@randall
Copy link
Contributor

randall commented Mar 21, 2022

@ezelkow1 can you kick off ci for this pr?

@ezelkow1
Copy link
Member

[approve ci]

@bryancall bryancall added this to the 10.0.0 milestone Mar 21, 2022
bool
HttpTransactCache::validate_ifrange_header_if_any(HTTPHdr *request, HTTPHdr *response)
{
if (!(request->presence(MIME_PRESENCE_RANGE) && request->presence(MIME_PRESENCE_IF_RANGE))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is MIME_PRESENCE_RANGE checked here, when it's already been checked at both call sites?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's only meant as a precautionary measure. Should I turn it into an assertion, or would it be better to remove it completely?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can remove with a comment if you like.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've fixed this in e0d44d7.

@SolidWallOfCode
Copy link
Member

Looks good overall. Excellent description!

@bryancall bryancall requested a review from traeak April 25, 2022 23:48
@traeak
Copy link
Contributor

traeak commented Jun 23, 2022

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?

@midchildan
Copy link
Contributor Author

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.

@traeak
Copy link
Contributor

traeak commented Jul 7, 2022

[approve ci autest]

@midchildan
Copy link
Contributor Author

#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.

@traeak
Copy link
Contributor

traeak commented Jul 28, 2022

Anything new on this PR?

@midchildan
Copy link
Contributor Author

midchildan commented Aug 8, 2022

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.

traeak
traeak previously approved these changes Aug 9, 2022
Copy link
Contributor

@traeak traeak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

everything looks okay

Copy link
Contributor

@traeak traeak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@traeak traeak merged commit 47f2db1 into apache:master Aug 15, 2022
@midchildan midchildan deleted the fix/if-range branch August 16, 2022 12:16
cmcfarlen pushed a commit to cmcfarlen/trafficserver that referenced this pull request Aug 23, 2022
* fix: properly process If-Range headers in client requests

* chore: add autest for range requests

* refactor: only check the presence of Range headers once
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants