Skip to content

Instantly share code, notes, and snippets.

@robertknight
Last active September 12, 2019 04:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robertknight/e31f6448f3341189a8485c3cb0188aed to your computer and use it in GitHub Desktop.
Save robertknight/e31f6448f3341189a8485c3cb0188aed to your computer and use it in GitHub Desktop.
Chrome range request + HTTP cache interaction issue

Steps to reproduce:

  1. Save range-request.html locally and open it in Chrome
  2. Clear your browser cache by going to chrome://settings/clearBrowserData, checking "Cached images and files" and clicking "Clear data"
  3. Open the devtools and make sure that the "Disable cache" option is not checked in the Network tab.
  4. Click the "Fetch file with Range requests" button. Observe the console logs and wait for the complete file to be fetched.
  5. Click the "Fetch file with one request" button and observe the console logs.
  6. Click the "Fetch file with one request" button again and observe the console logs.

Expected result:

In Safari 12 and Firefox 71, Step 4 produces a series of 206 responses and Steps 5 and 6 produce a single 200 response.

Actual result:

In Chrome 78.0.3902.4, Step 5 produces a 206 response with a Content-Range header indicating that the entire file has been fetched. Step 6 however produces a 200 response.

If the HTTP cache is cleared again and steps 4-6 are repeated, the same results occur.

<html>
<body>
<button id="fetchFileInRangesBtn">Fetch file with `Range` requests</button>
<button id="fetchFileBtn">Fetch file with one request</button>
<span id="resultLabel"></span>
<script>
const proxyUrl = "https://cors-anywhere.herokuapp.com";
const url = `${proxyUrl}/https://raw.githubusercontent.com/tpn/pdfs/master/100G%20Networking%20Technology%20Overview%20-%20Slides%20-%20Toronto%20(August%202016).pdf`;
async function fetchFileInRanges() {
let chunks = [];
let offset = 0;
const chunkSize = 200 * 1024;
while (true) {
console.log(`Fetching range ${offset}-${offset + chunkSize} of ${url}`);
const response = await fetch(url, {
headers: {
Range: `bytes=${offset}-${offset + chunkSize}`
}
});
console.log(`Fetch result: ${response.status}. Expected 206`);
let [,rangeStart,rangeEnd,length] = response.headers.get("Content-Range").match(
/bytes ([0-9]+)-([0-9]+)\/([0-9]+)/
);
rangeStart = Number(rangeStart);
rangeEnd = Number(rangeEnd);
length = Number(length);
console.log(`Fetched range ${rangeStart}-${rangeEnd} of ${length} bytes`);
if (rangeEnd + 1 >= length) {
break;
}
chunks.push(await response.arrayBuffer());
offset += chunkSize;
}
}
async function fetchFile() {
const response = await fetch(url);
const length = response.headers.get("Content-Length");
console.log(`Fetch result: ${response.status}. Expected 200`);
console.log(`Fetched file with ${length} bytes`);
}
fetchFileInRangesBtn.onclick = fetchFileInRanges;
fetchFileBtn.onclick = fetchFile;
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment