diff options
| author | David Lord <davidism@gmail.com> | 2020-02-05 18:10:38 -0800 |
|---|---|---|
| committer | David Lord <davidism@gmail.com> | 2020-02-05 18:17:32 -0800 |
| commit | 85eaee9b41dc16283d3a2a619ac4cc7cbdb8e6e0 (patch) | |
| tree | ffc46b4f7ddb247df7a11b6700aceb18eb6f6868 | |
| parent | 07e3c97d09a1d5e6fc17287855259380e496ee5c (diff) | |
| download | werkzeug-video-range.tar.gz | |
range request always returns 206 statusvideo-range
| -rw-r--r-- | CHANGES.rst | 3 | ||||
| -rw-r--r-- | src/werkzeug/wrappers/etag.py | 29 | ||||
| -rw-r--r-- | tests/test_wrappers.py | 4 |
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 |
