From 1d48e9c2017730f9fbab6267655f109b58be3f2d Mon Sep 17 00:00:00 2001
From: Mack Duan <duan.mack@gmail.com>
Date: Thu, 25 Apr 2013 10:57:40 -0700
Subject: [PATCH] Handle server returning 200 for range request

---
 src/chunked_stream.js |  3 ++-
 src/network.js        | 19 +++++++++++++++----
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/src/chunked_stream.js b/src/chunked_stream.js
index fe8388aa1..bef636147 100644
--- a/src/chunked_stream.js
+++ b/src/chunked_stream.js
@@ -363,7 +363,8 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
       var loadedRequests = [];
       for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
 
-        var requestIds = this.requestsByChunk[chunk];
+        // The server might return more chunks than requested
+        var requestIds = this.requestsByChunk[chunk] || [];
         delete this.requestsByChunk[chunk];
 
         for (var i = 0; i < requestIds.length; ++i) {
diff --git a/src/network.js b/src/network.js
index 44e3847dd..b3981febd 100644
--- a/src/network.js
+++ b/src/network.js
@@ -40,6 +40,10 @@ function log(aMsg) {
 //#endif
 
 var NetworkManager = (function NetworkManagerClosure() {
+
+  var OK_RESPONSE = 200;
+  var PARTIAL_CONTENT_RESPONSE = 206;
+
   function NetworkManager(url, args) {
     this.url = url;
     args = args || {};
@@ -160,7 +164,15 @@ var NetworkManager = (function NetworkManagerClosure() {
         return;
       }
 
-      if (xhr.status !== pendingRequest.expectedStatus) {
+      // From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2:
+      // "A server MAY ignore the Range header". This means it's possible to
+      // get a 200 rather than a 206 response from a range request.
+      var ok_response_on_range_request =
+          xhr.status === OK_RESPONSE &&
+          pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
+
+      if (!ok_response_on_range_request &&
+          xhr.status !== pendingRequest.expectedStatus) {
         if (pendingRequest.onError) {
           pendingRequest.onError(xhr.status);
         }
@@ -170,18 +182,17 @@ var NetworkManager = (function NetworkManagerClosure() {
       this.loadedRequests[xhrId] = true;
 
       var chunk = getArrayBuffer(xhr);
-      if (pendingRequest.expectedStatus === 206) {
+      if (xhr.status === PARTIAL_CONTENT_RESPONSE) {
         var rangeHeader = xhr.getResponseHeader('Content-Range');
         var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
         var begin = parseInt(matches[1], 10);
-        var end = parseInt(matches[2], 10) + 1;
         pendingRequest.onDone({
           begin: begin,
-          end: end,
           chunk: chunk
         });
       } else {
         pendingRequest.onDone({
+          begin: 0,
           chunk: chunk
         });
       }