Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

range request always returns 206 status #1711

Merged
merged 1 commit into from
Feb 6, 2020
Merged
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
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
29 changes: 16 additions & 13 deletions src/werkzeug/wrappers/etag.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,28 +142,31 @@ def _process_range_request(self, environ, complete_length=None, accept_ranges=No
"""
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
Expand Down
4 changes: 2 additions & 2 deletions tests/test_wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down