From 2506c0b9a96d48f14624acfa552fc88e38a542ae Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sat, 8 Feb 2014 17:45:09 +0000 Subject: [PATCH] Fixed sending etags for file streams with a name. This fixes #930. --- CHANGES | 1 + flask/helpers.py | 21 +++++++++++++-------- flask/testsuite/helpers.py | 11 +++++++++++ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 0737c590..8b76c5fc 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,7 @@ Version 0.10.2 - Fixed an issue with query parameters getting removed from requests in the test client when absolute URLs were requested. - Made `@before_first_request` into a decorator as intended. +- Fixed an etags bug when sending a file without a name. Version 0.10.1 -------------- diff --git a/flask/helpers.py b/flask/helpers.py index c71da85b..7b69b63c 100644 --- a/flask/helpers.py +++ b/flask/helpers.py @@ -538,14 +538,19 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False, rv.expires = int(time() + cache_timeout) if add_etags and filename is not None: - rv.set_etag('flask-%s-%s-%s' % ( - os.path.getmtime(filename), - os.path.getsize(filename), - adler32( - filename.encode('utf-8') if isinstance(filename, text_type) - else filename - ) & 0xffffffff - )) + try: + rv.set_etag('flask-%s-%s-%s' % ( + os.path.getmtime(filename), + os.path.getsize(filename), + adler32( + filename.encode('utf-8') if isinstance(filename, text_type) + else filename + ) & 0xffffffff + )) + except OSError: + warn('Access %s failed, maybe it does not exist, so ignore etags in ' + 'headers' % filename, stacklevel=2) + if conditional: rv = rv.make_conditional(request) # make sure we don't send x-sendfile for servers that diff --git a/flask/testsuite/helpers.py b/flask/testsuite/helpers.py index 518d9384..c645dc14 100644 --- a/flask/testsuite/helpers.py +++ b/flask/testsuite/helpers.py @@ -264,6 +264,17 @@ class SendfileTestCase(FlaskTestCase): rv.close() # etags self.assert_equal(len(captured), 1) + with catch_warnings() as captured: + from StringIO import StringIO as PYStringIO + f = PYStringIO('Test') + f.name = 'test.txt' + rv = flask.send_file(f) + rv.direct_passthrough = False + self.assert_equal(rv.data, b'Test') + self.assert_equal(rv.mimetype, 'text/plain') + rv.close() + # attachment_filename and etags + self.assert_equal(len(captured), 3) with catch_warnings() as captured: f = StringIO('Test') rv = flask.send_file(f, mimetype='text/plain')