Commits

Robert Brewer  committed f21580c

Fix to 2.1, 2.2, 3.0 for bugs in Range slicing and final boundary. Also made the output match Apache output (CRLFs).

  • Participants
  • Parent commits 39ccf20

Comments (0)

Files changed (2)

File cherrypy/lib/static.py

 ##                del response.headers['Content-Length']
                 
                 def file_ranges():
+                    # Apache compatibility:
+                    yield "\r\n"
+                    
                     for start, stop in r:
                         yield "--" + boundary
-                        yield "\nContent-type: %s" % content_type
-                        yield ("\nContent-range: bytes %s-%s/%s\n\n"
+                        yield "\r\nContent-type: %s" % content_type
+                        yield ("\r\nContent-range: bytes %s-%s/%s\r\n\r\n"
                                % (start, stop - 1, c_len))
                         bodyfile.seek(start)
-                        yield bodyfile.read((stop + 1) - start)
-                        yield "\n"
+                        yield bodyfile.read(stop - start)
+                        yield "\r\n"
                     # Final boundary
-                    yield "--" + boundary
+                    yield "--" + boundary + "--"
+                    
+                    # Apache compatibility:
+                    yield "\r\n"
                 response.body = file_ranges()
         else:
             response.headers['Content-Length'] = c_len

File cherrypy/test/test_core.py

     
     class Ranges(Test):
         
-        def get_ranges(self):
-            h = cherrypy.request.headers.get('Range')
-            return repr(http.get_ranges(h, 8))
+        def get_ranges(self, bytes):
+            return repr(http.get_ranges('bytes=%s' % bytes, 8))
         
         def slice_file(self):
             path = os.path.join(os.getcwd(), os.path.dirname(__file__))
         self.assertInBody("raise ValueError()")
     
     def testRanges(self):
-        self.getPage("/ranges/get_ranges", [('Range', 'bytes=3-6')])
+        self.getPage("/ranges/get_ranges?bytes=3-6")
         self.assertBody("[(3, 7)]")
         
         # Test multiple ranges and a suffix-byte-range-spec, for good measure.
-        self.getPage("/ranges/get_ranges", [('Range', 'bytes=2-4,-1')])
+        self.getPage("/ranges/get_ranges?bytes=2-4,-1")
         self.assertBody("[(2, 5), (7, 8)]")
         
         # Get a partial file.
             # What happens with overlapping ranges (and out of order, too)?
             self.getPage("/ranges/slice_file", [('Range', 'bytes=4-6,2-5')])
             self.assertStatus(206)
-            ct = ""
-            for k, v in self.headers:
-                if k.lower() == "content-type":
-                    ct = v
-                    break
+            ct = self.assertHeader("Content-Type")
             expected_type = "multipart/byteranges; boundary="
             self.assert_(ct.startswith(expected_type))
             boundary = ct[len(expected_type):]
-            expected_body = """--%s
-Content-type: text/html
-Content-range: bytes 4-6/14
-
-o, w
---%s
-Content-type: text/html
-Content-range: bytes 2-5/14
-
-llo, 
---%s""" % (boundary, boundary, boundary)
+            expected_body = ("\r\n--%s\r\n"
+                             "Content-type: text/html\r\n"
+                             "Content-range: bytes 4-6/14\r\n"
+                             "\r\n"
+                             "o, \r\n"
+                             "--%s\r\n"
+                             "Content-type: text/html\r\n"
+                             "Content-range: bytes 2-5/14\r\n"
+                             "\r\n"
+                             "llo,\r\n"
+                             "--%s--\r\n" % (boundary, boundary, boundary))
             self.assertBody(expected_body)
             self.assertHeader("Content-Length")
             
             # Test "416 Requested Range Not Satisfiable"
             self.getPage("/ranges/slice_file", [('Range', 'bytes=2300-2900')])
             self.assertStatus(416)
+            # "When this status code is returned for a byte-range request,
+            # the response SHOULD include a Content-Range entity-header
+            # field specifying the current length of the selected resource"
             self.assertHeader("Content-Range", "bytes */14")
         elif cherrypy.server.protocol_version == "HTTP/1.0":
             # Test Range behavior with HTTP/1.0 request