Handle range request on a truncated entry
This change will doom the truncated entry and creates a new sparse entry.
TEST=unit tests
Review URL: http://codereview.chromium.org/251067
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27859 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index c1c3478..b6a8bc33c 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -969,8 +969,10 @@
if (!partial_->UpdateFromStoredHeaders(response_.headers, entry_->disk_entry,
truncated_)) {
// The stored data cannot be used. Get rid of it and restart this request.
+ // We need to also reset the |truncated_| flag as a new entry is created.
DoomPartialEntry(!byte_range_requested);
mode_ = WRITE;
+ truncated_ = false;
return AddToEntry();
}
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index 064f7c4..ea98c67 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -2541,6 +2541,50 @@
entry->Close();
}
+// Tests that we can handle range requests when we have a truncated entry.
+TEST(HttpCache, RangeGET_IncompleteResource) {
+ MockHttpCache cache;
+ cache.http_cache()->set_enable_range_support(true);
+ AddMockTransaction(&kRangeGET_TransactionOK);
+
+ // Create a disk cache entry that stores an incomplete resource.
+ disk_cache::Entry* entry;
+ ASSERT_TRUE(cache.disk_cache()->CreateEntry(kRangeGET_TransactionOK.url,
+ &entry));
+
+ // Content-length will be intentionally bogus.
+ std::string raw_headers("HTTP/1.1 200 OK\n"
+ "Last-Modified: something\n"
+ "ETag: \"foo\"\n"
+ "Accept-Ranges: bytes\n"
+ "Content-Length: 10\n");
+ raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(),
+ raw_headers.size());
+
+ net::HttpResponseInfo response;
+ response.headers = new net::HttpResponseHeaders(raw_headers);
+ // Set the last argument for this to be an incomplete request.
+ EXPECT_TRUE(net::HttpCache::WriteResponseInfo(entry, &response, true, true));
+
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100));
+ int len = static_cast<int>(base::strlcpy(buf->data(),
+ "rg: 00-09 rg: 10-19 ", 100));
+ EXPECT_EQ(len, entry->WriteData(1, 0, buf, len, NULL, true));
+ entry->Close();
+
+ // Now make a range request.
+ std::string headers;
+ RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
+ &headers);
+
+ EXPECT_TRUE(Verify206Response(headers, 40, 49));
+ EXPECT_EQ(1, cache.network_layer()->transaction_count());
+ EXPECT_EQ(1, cache.disk_cache()->open_count());
+ EXPECT_EQ(2, cache.disk_cache()->create_count());
+
+ RemoveMockTransaction(&kRangeGET_TransactionOK);
+}
+
TEST(HttpCache, SyncRead) {
MockHttpCache cache;
diff --git a/net/http/partial_data.cc b/net/http/partial_data.cc
index 7257f00..b61d9be 100644
--- a/net/http/partial_data.cc
+++ b/net/http/partial_data.cc
@@ -120,14 +120,13 @@
resource_size_ = 0;
if (truncated) {
DCHECK_EQ(headers->response_code(), 200);
- truncated_ = true;
- sparse_entry_ = false;
-
// We don't have the real length and the user may be trying to create a
// sparse entry so let's not write to this entry.
if (byte_range_.IsValid())
return false;
+ truncated_ = true;
+ sparse_entry_ = false;
byte_range_.set_first_byte_position(entry->GetDataSize(kDataStream));
current_range_start_ = 0;
return true;