Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion tornado/httputil.py
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,8 @@ def _parse_request_range(
(None, 0)
>>> _parse_request_range("bytes=")
(None, None)
>>> _parse_request_range("BYTES=1-2")
(1, 3)
>>> _parse_request_range("foo=42")
>>> _parse_request_range("bytes=1-2,6-10")

Expand All @@ -885,7 +887,7 @@ def _parse_request_range(
"""
unit, _, value = range_header.partition("=")
unit, value = unit.strip(), value.strip()
if unit != "bytes":
if unit.lower() != "bytes":
return None
start_b, _, end_b = value.partition("-")
try:
Expand Down
26 changes: 26 additions & 0 deletions tornado/test/httputil_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
HTTPServerRequest,
ParseMultipartConfig,
RequestStartLine,
_parse_request_range,
format_timestamp,
parse_cookie,
parse_multipart_form_data,
Expand Down Expand Up @@ -623,6 +624,31 @@ def test_parse_request_start_line(self):
self.assertEqual(parsed_start_line.version, self.VERSION)


class ParseRequestRangeTest(unittest.TestCase):
"""Tests for httputil._parse_request_range."""

def test_lowercase_unit(self):
self.assertEqual(_parse_request_range("bytes=1-2"), (1, 3))

def test_uppercase_unit_accepted(self):
# Per RFC 7233 section 2.1: "all rules derived from token are to be
# compared case-insensitively, like range-unit and acceptable-ranges."
# Pre-fix, an uppercase "BYTES" unit returned None.
self.assertEqual(_parse_request_range("BYTES=1-2"), (1, 3))

def test_mixed_case_unit_accepted(self):
self.assertEqual(_parse_request_range("Bytes=1-2"), (1, 3))
self.assertEqual(_parse_request_range("bYtEs=1-2"), (1, 3))

def test_uppercase_unit_with_suffix_range(self):
self.assertEqual(_parse_request_range("BYTES=6-"), (6, None))
self.assertEqual(_parse_request_range("BYTES=-6"), (-6, None))

def test_non_bytes_unit_still_rejected(self):
# An unknown unit is rejected regardless of case.
self.assertIsNone(_parse_request_range("items=1-2"))


class ParseCookieTest(unittest.TestCase):
# These tests copied from Django:
# https://github.com/django/django/pull/6277/commits/da810901ada1cae9fc1f018f879f11a7fb467b28
Expand Down
Loading