self.assertEqual(response.headers.get("Content-Length"), "4")
self.assertEqual(response.headers.get("Content-Range"), "bytes 22-25/26")
+ def test_static_with_range_neg_past_start(self):
+ response = self.get_and_head(
+ "/static/robots.txt", headers={"Range": "bytes=-1000000"}
+ )
+ self.assertEqual(response.code, 200)
+ robots_file_path = os.path.join(self.static_dir, "robots.txt")
+ with open(robots_file_path) as f:
+ self.assertEqual(response.body, utf8(f.read()))
+ self.assertEqual(response.headers.get("Content-Length"), "26")
+ self.assertEqual(response.headers.get("Content-Range"), None)
+
def test_static_invalid_range(self):
response = self.get_and_head("/static/robots.txt", headers={"Range": "asdf"})
self.assertEqual(response.code, 200)
self.assertEqual(response.code, 416)
self.assertEqual(response.headers.get("Content-Range"), "bytes */26")
+ def test_static_unsatisfiable_range_end_less_than_start(self):
+ response = self.get_and_head(
+ "/static/robots.txt", headers={"Range": "bytes=10-3"}
+ )
+ self.assertEqual(response.code, 416)
+ self.assertEqual(response.headers.get("Content-Range"), "bytes */26")
+
def test_static_head(self):
response = self.fetch("/static/robots.txt", method="HEAD")
self.assertEqual(response.code, 200)
size = self.get_content_size()
if request_range:
start, end = request_range
- if (start is not None and start >= size) or end == 0:
+ if start is not None and start < 0:
+ start += size
+ if start < 0:
+ start = 0
+ if (
+ start is not None
+ and (start >= size or (end is not None and start >= end))
+ ) or end == 0:
# As per RFC 2616 14.35.1, a range is not satisfiable only: if
# the first requested byte is equal to or greater than the
- # content, or when a suffix with length 0 is specified
+ # content, or when a suffix with length 0 is specified.
+ # https://tools.ietf.org/html/rfc7233#section-2.1
+ # A byte-range-spec is invalid if the last-byte-pos value is present
+ # and less than the first-byte-pos.
self.set_status(416) # Range Not Satisfiable
self.set_header("Content-Type", "text/plain")
self.set_header("Content-Range", "bytes */%s" % (size,))
return
- if start is not None and start < 0:
- start += size
if end is not None and end > size:
# Clients sometimes blindly use a large range to limit their
# download size; cap the endpoint at the actual file size.