diff --git a/CHANGES b/CHANGES index 294829ff..2cb24c20 100644 --- a/CHANGES +++ b/CHANGES @@ -148,6 +148,14 @@ Major release, unreleased .. _#2436: https://github.com/pallets/flask/pull/2436 .. _#2450: https://github.com/pallets/flask/pull/2450 +Version 0.12.3 +-------------- + +Bugfix release, unreleased + +- Fix a ValueError caused by invalid Range requests in some cases + + Version 0.12.2 -------------- diff --git a/flask/helpers.py b/flask/helpers.py index efec454c..f1011ad0 100644 --- a/flask/helpers.py +++ b/flask/helpers.py @@ -610,7 +610,8 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False, rv = rv.make_conditional(request, accept_ranges=True, complete_length=fsize) except RequestedRangeNotSatisfiable: - file.close() + if file is not None: + file.close() raise else: rv = rv.make_conditional(request) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index cc480c26..066f3687 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -506,7 +506,7 @@ class TestSendfile(object): @pytest.mark.skipif( not callable(getattr(Range, 'to_content_range_header', None)), - reason="not implement within werkzeug" + reason="not implemented within werkzeug" ) def test_send_file_range_request(self, app, client): @app.route('/') @@ -563,7 +563,28 @@ class TestSendfile(object): assert rv.status_code == 200 rv.close() + @pytest.mark.skipif( + not callable(getattr(Range, 'to_content_range_header', None)), + reason="not implemented within werkzeug" + ) + def test_send_file_range_request_xsendfile_invalid(self, app, client): + # https://github.com/pallets/flask/issues/2526 + app.use_x_sendfile = True + + rv = client.get('/', headers={'Range': 'bytes=1000-'}) + assert rv.status_code == 416 + rv.close() + def test_attachment(self, app, req_ctx): + app = flask.Flask(__name__) + with app.test_request_context(): + with open(os.path.join(app.root_path, 'static/index.html')) as f: + rv = flask.send_file(f, as_attachment=True, + attachment_filename='index.html') + value, options = \ + parse_options_header(rv.headers['Content-Disposition']) + assert value == 'attachment' + rv.close() with open(os.path.join(app.root_path, 'static/index.html')) as f: rv = flask.send_file(f, as_attachment=True,