You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2010/08/25 10:17:19 UTC

svn commit: r988866 - in /couchdb/trunk: share/www/script/test/attachment_ranges.js src/couchdb/couch_httpd_db.erl src/mochiweb/mochiweb_http.erl

Author: rnewson
Date: Wed Aug 25 08:17:19 2010
New Revision: 988866

URL: http://svn.apache.org/viewvc?rev=988866&view=rev
Log:
COUCHDB-161 - range support. Adhere closer to the spec. correct range parsing error in mochiweb.

Modified:
    couchdb/trunk/share/www/script/test/attachment_ranges.js
    couchdb/trunk/src/couchdb/couch_httpd_db.erl
    couchdb/trunk/src/mochiweb/mochiweb_http.erl

Modified: couchdb/trunk/share/www/script/test/attachment_ranges.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/attachment_ranges.js?rev=988866&r1=988865&r2=988866&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/attachment_ranges.js (original)
+++ couchdb/trunk/share/www/script/test/attachment_ranges.js Wed Aug 25 08:17:19 2010
@@ -37,28 +37,29 @@ couchTests.attachment_ranges = function(
             "Range": "bytes=0-28"
         }
     });
-    TEquals(206, xhr.status);
+    TEquals(206, xhr.status, "fetch 0-28");
     TEquals("This is a base64 encoded text", xhr.responseText);
     TEquals("bytes 0-28/29", xhr.getResponseHeader("Content-Range"));
     TEquals("29", xhr.getResponseHeader("Content-Length"));
 
-    // Fetch the whole entity without an end offset is a 200.
+    // Fetch the whole entity without an end offset is a 206.
     var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo.txt", {
         headers: {
             "Range": "bytes=0-"
         }
     });
-    TEquals(200, xhr.status);
+    TEquals(206, xhr.status, "fetch 0-");
     TEquals("This is a base64 encoded text", xhr.responseText);
+    TEquals("bytes 0-28/29", xhr.getResponseHeader("Content-Range"));
     TEquals("29", xhr.getResponseHeader("Content-Length"));
 
-    // Badly formed range header is a 400.
+    // Badly formed range header is a 200.
     var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo.txt", {
         headers: {
             "Range": "bytes:0-"
         }
     });
-    TEquals(400, xhr.status);
+    TEquals(200, xhr.status, "fetch with bad range header");
 
     // Fetch the end of an entity without an end offset is a 206.
     var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo.txt", {
@@ -66,18 +67,20 @@ couchTests.attachment_ranges = function(
             "Range": "bytes=2-"
         }
     });
-    TEquals(206, xhr.status);
+    TEquals(206, xhr.status, "fetch 2-");
     TEquals("is is a base64 encoded text", xhr.responseText);
     TEquals("bytes 2-28/29", xhr.getResponseHeader("Content-Range"));
     TEquals("27", xhr.getResponseHeader("Content-Length"));
 
-    // Fetch past the end of the entity is a 416
+    // Fetch past the end of the entity is a 206
     var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo.txt", {
         headers: {
             "Range": "bytes=0-29"
         }
     });
-    TEquals(416, xhr.status);
+    TEquals(206, xhr.status, "fetch 0-29");
+    TEquals("bytes 0-28/29", xhr.getResponseHeader("Content-Range"));
+    TEquals("29", xhr.getResponseHeader("Content-Length"));
 
     // Fetch first part of entity is a 206
     var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo.txt", {
@@ -85,7 +88,7 @@ couchTests.attachment_ranges = function(
             "Range": "bytes=0-3"
         }
     });
-    TEquals(206, xhr.status);
+    TEquals(206, xhr.status, "fetch 0-3");
     TEquals("This", xhr.responseText);
     TEquals("4", xhr.getResponseHeader("Content-Length"));
     TEquals("bytes 0-3/29", xhr.getResponseHeader("Content-Range"));
@@ -96,7 +99,7 @@ couchTests.attachment_ranges = function(
             "Range": "bytes=10-15"
         }
     });
-    TEquals(206, xhr.status);
+    TEquals(206, xhr.status, "fetch 10-15");
     TEquals("base64", xhr.responseText);
     TEquals("6", xhr.getResponseHeader("Content-Length"));
     TEquals("bytes 10-15/29", xhr.getResponseHeader("Content-Range"));
@@ -107,10 +110,25 @@ couchTests.attachment_ranges = function(
             "Range": "bytes=-3"
         }
     });
-    TEquals(206, xhr.status);
+    TEquals(206, xhr.status, "fetch -3");
     TEquals("ext", xhr.responseText);
     TEquals("3", xhr.getResponseHeader("Content-Length"));
     TEquals("bytes 26-28/29", xhr.getResponseHeader("Content-Range"));
+    
+    // backward range is 416
+    var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo.txt", {
+       headers: {
+           "Range": "bytes=5-3"
+       }
+    });
+    TEquals(416, xhr.status, "fetch 5-3");
 
+    // range completely outside of entity is 416
+    var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo.txt", {
+        headers: {
+            "Range": "bytes=300-310"
+        }
+    });
+    TEquals(416, xhr.status, "fetch 300-310");
 
 };

Modified: couchdb/trunk/src/couchdb/couch_httpd_db.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_db.erl?rev=988866&r1=988865&r2=988866&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd_db.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd_db.erl Wed Aug 25 08:17:19 2010
@@ -1086,29 +1086,23 @@ db_attachment_req(Req, _Db, _DocId, _Fil
 
 parse_ranges(undefined, _Len) ->
     undefined;
-parse_ranges(fail, _Len) ->
-    throw(bad_request);
+parse_ranges(fail, Len) ->
+    undefined;
 parse_ranges(Ranges, Len) ->
     parse_ranges(Ranges, Len, []).
 
 parse_ranges([], _Len, Acc) ->
     lists:reverse(Acc);
+parse_ranges([{From, To}|_], Len, _Acc) when is_integer(From) andalso is_integer(To) andalso To < From ->
+    throw(requested_range_not_satisfiable);
+parse_ranges([{From, To}|Rest], Len, Acc) when is_integer(To) andalso To >= Len ->
+    parse_ranges([{From, Len-1}] ++ Rest, Len, Acc);
+parse_ranges([{none, To}|Rest], Len, Acc) ->
+    parse_ranges([{Len - To, Len - 1}] ++ Rest, Len, Acc);
+parse_ranges([{From, none}|Rest], Len, Acc) ->
+    parse_ranges([{From, Len - 1}] ++ Rest, Len, Acc);
 parse_ranges([{From,To}|Rest], Len, Acc) ->
-    {From1, To1} = case {From, To} of
-        {none, To} ->
-            {Len - To, Len - 1};
-        {From, none} ->
-            {From, Len - 1};
-        _ ->
-            {From, To}
-        end,
-    if
-        From < 0 orelse To1 >= Len ->
-            throw(requested_range_not_satisfiable);
-        true ->
-            ok
-    end,
-    parse_ranges(Rest, Len, [{From1, To1}] ++ Acc).
+    parse_ranges(Rest, Len, [{From, To}] ++ Acc).
 
 get_md5_header(Req) ->
     ContentMD5 = couch_httpd:header_value(Req, "Content-MD5"),

Modified: couchdb/trunk/src/mochiweb/mochiweb_http.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/mochiweb/mochiweb_http.erl?rev=988866&r1=988865&r2=988866&view=diff
==============================================================================
--- couchdb/trunk/src/mochiweb/mochiweb_http.erl (original)
+++ couchdb/trunk/src/mochiweb/mochiweb_http.erl Wed Aug 25 08:17:19 2010
@@ -162,8 +162,6 @@ after_response(Body, Req) ->
             ?MODULE:loop(Socket, Body)
     end.
 
-parse_range_request("bytes=0-") ->
-    undefined;
 parse_range_request(RawRange) when is_list(RawRange) ->
     try
         "bytes=" ++ RangeString = RawRange,