diff --git a/src/iocore/cache/CacheRead.cc b/src/iocore/cache/CacheRead.cc index 7565d9f761e..894678a2b15 100644 --- a/src/iocore/cache/CacheRead.cc +++ b/src/iocore/cache/CacheRead.cc @@ -1105,6 +1105,10 @@ CacheVC::openReadStartHead(int event, Event *e) } // the first fragment might have been gc'ed. Make sure the first // fragment is there before returning CACHE_EVENT_OPEN_READ + // For zero-length documents, don't attempt to read additional fragments. + if (doc_len == 0 && !f.single_fragment) { + f.single_fragment = true; + } if (!f.single_fragment) { goto Learliest; } diff --git a/tests/gold_tests/cache/replay/negative-revalidating-enabled.replay.yaml b/tests/gold_tests/cache/replay/negative-revalidating-enabled.replay.yaml index 32c5ad66ebf..607c3816d34 100644 --- a/tests/gold_tests/cache/replay/negative-revalidating-enabled.replay.yaml +++ b/tests/gold_tests/cache/replay/negative-revalidating-enabled.replay.yaml @@ -81,6 +81,29 @@ sessions: proxy-response: status: 200 + # Also populate cache with a zero-length response (for issue #6649). + - client-request: + method: "GET" + version: "1.1" + scheme: "http" + url: /path/zero_length_item + headers: + fields: + - [ Host, example.com ] + - [ uuid, 31 ] + + # Populate the cache with a 200 response with zero-length content. + server-response: + status: 200 + reason: "OK" + headers: + fields: + - [ Content-Length, 0 ] + - [ Cache-Control, max-age=2 ] + + proxy-response: + status: 200 + # Verify we serve the 200 OK out of the cache if it is not stale. - client-request: method: "GET" @@ -107,6 +130,29 @@ sessions: proxy-response: status: 200 + # Verify zero-length is also served from cache when fresh. + - client-request: + method: "GET" + version: "1.1" + scheme: "http" + url: /path/zero_length_item + headers: + fields: + - [ Host, example.com ] + - [ uuid, 32 ] + + # This should not reach the origin server. + server-response: + status: 503 + reason: "Service Unavailable" + headers: + fields: + - [ Content-Length, 0 ] + + # Again, we should serve this out of the cache. + proxy-response: + status: 200 + # Verify that with negative_revalidating enabled, we serve the 200 OK out of # the cache even though it is stale (but younger than max-age + max_stale_age). - client-request: @@ -134,6 +180,54 @@ sessions: proxy-response: status: 200 + # Test zero-length while stale - first request (regression test for issue #6649). + - client-request: + method: "GET" + version: "1.1" + scheme: "http" + url: /path/zero_length_item + headers: + fields: + - [ Host, example.com ] + - [ uuid, 33 ] + + server-response: + status: 503 + reason: "Service Unavailable" + headers: + fields: + - [ Content-Length, 0 ] + + # With negative_revalidating enabled, the cached response should be served + # even though it is stale. + proxy-response: + status: 200 + + # Make a second consecutive stale request for zero-length to verify the bug scenario. + # Per issue #6649: "only the first get on a 0 length cached object comes back + # as stale and the second succeeds" (meaning the second might fail). + - client-request: + method: "GET" + version: "1.1" + scheme: "http" + url: /path/zero_length_item + headers: + fields: + - [ Host, example.com ] + - [ uuid, 34 ] + + server-response: + status: 503 + reason: "Service Unavailable" + headers: + fields: + - [ Content-Length, 0 ] + + # This second consecutive stale request should also be served from cache. + # This is where the #6649 bug manifests - without the fix, it returns 503. + proxy-response: + status: 200 + # Verify that max_stale_age is respected. - client-request: method: "GET" @@ -161,6 +255,29 @@ sessions: proxy-response: status: 503 + # Verify max_stale_age is also respected for zero-length responses. + - client-request: + method: "GET" + version: "1.1" + scheme: "http" + url: /path/zero_length_item + headers: + fields: + - [ Host, example.com ] + - [ uuid, 35 ] + + server-response: + status: 503 + reason: "Service Unavailable" + headers: + fields: + - [ Content-Length, 0 ] + + # negative_revalidating is enabled, but now the cached item is older than + # max_stale_age. + proxy-response: + status: 503 + # # Test 2: Negative revalidating for a cached chunk encoded response. #