summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lord <davidism@gmail.com>2020-02-05 18:10:38 -0800
committerDavid Lord <davidism@gmail.com>2020-02-05 18:17:32 -0800
commit85eaee9b41dc16283d3a2a619ac4cc7cbdb8e6e0 (patch)
treeffc46b4f7ddb247df7a11b6700aceb18eb6f6868
parent07e3c97d09a1d5e6fc17287855259380e496ee5c (diff)
downloadwerkzeug-video-range.tar.gz
range request always returns 206 statusvideo-range
-rw-r--r--CHANGES.rst3
-rw-r--r--src/werkzeug/wrappers/etag.py29
-rw-r--r--tests/test_wrappers.py4
3 files changed, 21 insertions, 15 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 54ac12db..ae5fba0a 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -98,6 +98,9 @@ Unreleased
implementations. :pr:`1702`
- Support matching and building WebSocket rules in the routing system,
for use by async frameworks. :pr:`1709`
+- Range requests that span an entire file respond with 206 instead of
+ 200, to be more compliant with :rfc:`7233`. This may help serving
+ media to older browsers. :issue:`410, 1704`
Version 0.16.1
diff --git a/src/werkzeug/wrappers/etag.py b/src/werkzeug/wrappers/etag.py
index ac2860a0..460629bd 100644
--- a/src/werkzeug/wrappers/etag.py
+++ b/src/werkzeug/wrappers/etag.py
@@ -142,28 +142,31 @@ class ETagResponseMixin(object):
"""
from ..exceptions import RequestedRangeNotSatisfiable
- if accept_ranges is None:
- return False
- self.headers["Accept-Ranges"] = accept_ranges
- if not self._is_range_request_processable(environ) or complete_length is None:
+ if (
+ accept_ranges is None
+ or complete_length is None
+ or not self._is_range_request_processable(environ)
+ ):
return False
+
parsed_range = parse_range_header(environ.get("HTTP_RANGE"))
+
if parsed_range is None:
raise RequestedRangeNotSatisfiable(complete_length)
+
range_tuple = parsed_range.range_for_length(complete_length)
content_range_header = parsed_range.to_content_range_header(complete_length)
+
if range_tuple is None or content_range_header is None:
raise RequestedRangeNotSatisfiable(complete_length)
+
content_length = range_tuple[1] - range_tuple[0]
- # Be sure not to send 206 response
- # if requested range is the full content.
- if content_length != complete_length:
- self.headers["Content-Length"] = content_length
- self.content_range = content_range_header
- self.status_code = 206
- self._wrap_response(range_tuple[0], content_length)
- return True
- return False
+ self.headers["Content-Length"] = content_length
+ self.headers["Accept-Ranges"] = accept_ranges
+ self.content_range = content_range_header
+ self.status_code = 206
+ self._wrap_response(range_tuple[0], content_length)
+ return True
def make_conditional(
self, request_or_environ, accept_ranges=False, complete_length=None
diff --git a/tests/test_wrappers.py b/tests/test_wrappers.py
index 6973a1c5..7e21eda7 100644
--- a/tests/test_wrappers.py
+++ b/tests/test_wrappers.py
@@ -878,9 +878,9 @@ def test_range_request_with_complete_file():
response = wrappers.Response(wrap_file(env, f))
env["HTTP_RANGE"] = "bytes=0-%d" % (fsize - 1)
response.make_conditional(env, accept_ranges=True, complete_length=fsize)
- assert response.status_code == 200
+ assert response.status_code == 206
assert response.headers["Accept-Ranges"] == "bytes"
- assert "Content-Range" not in response.headers
+ assert response.headers["Content-Range"] == "bytes 0-%d/%d" % (fsize - 1, fsize)
assert response.headers["Content-Length"] == str(fsize)
assert response.data == fcontent