From d1b23a1900d5ccc2aae56c4bb475f9640cb9a455 Mon Sep 17 00:00:00 2001 From: Bert JW Regeer Date: Mon, 17 Jan 2022 16:17:52 -0700 Subject: [PATCH 1/3] Add tests to validate wsgi.file_wrapper seek/tell are added --- tests/test_buffers.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_buffers.py b/tests/test_buffers.py index 01cdc2de..b37949b8 100644 --- a/tests/test_buffers.py +++ b/tests/test_buffers.py @@ -185,6 +185,8 @@ def tearDown(self): def test_prepare_not_seekable(self): f = KindaFilelike(b"abc") inst = self._makeOne(f) + self.assertFalse(hasattr(inst, "seek")) + self.assertFalse(hasattr(inst, "tell")) result = inst.prepare() self.assertEqual(result, False) self.assertEqual(inst.remain, 0) @@ -200,6 +202,8 @@ def test_prepare_not_seekable_closeable(self): def test_prepare_seekable_closeable(self): f = Filelike(b"abc", close=1, tellresults=[0, 10]) inst = self._makeOne(f) + self.assertEqual(inst.seek, f.seek) + self.assertEqual(inst.tell, f.tell) result = inst.prepare() self.assertEqual(result, 10) self.assertEqual(inst.remain, 10) From 8423ffac8f2f32ed501d225f9f4f6893511212a7 Mon Sep 17 00:00:00 2001 From: Bert JW Regeer Date: Mon, 17 Jan 2022 16:19:29 -0700 Subject: [PATCH 2/3] Add support for seekable wsgi.file_wrapper --- src/waitress/buffers.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/waitress/buffers.py b/src/waitress/buffers.py index 386eb40f..8091ff0e 100644 --- a/src/waitress/buffers.py +++ b/src/waitress/buffers.py @@ -145,6 +145,16 @@ def __init__(self, file, block_size=32768): self.file = file self.block_size = block_size # for __iter__ + # This is for the benefit of anyone that is attempting to wrap this + # wsgi.file_wrapper in a WSGI middleware and wants to seek, this is + # useful for instance for support Range requests + if _is_seekable(self.file): + if hasattr(self.file, "seekable"): + self.seekable = self.file.seekable + + self.seek = self.file.seek + self.tell = self.file.tell + def prepare(self, size=None): if _is_seekable(self.file): start_pos = self.file.tell() From 5627a4c322ae02c79bb61e531fc6bf8e0a69c9b8 Mon Sep 17 00:00:00 2001 From: Bert JW Regeer Date: Mon, 17 Jan 2022 16:24:56 -0700 Subject: [PATCH 3/3] Add CHANGELOG for wsgi.file_wrapper seek/tell attrs --- CHANGES.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 5ccaa642..888c31b5 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -11,6 +11,13 @@ Python Version Support Bugfix ~~~~~~ +- ``wsgi.file_wrapper`` now sets the ``seekable``, ``seek``, and ``tell`` attributes from + the underlying file if the underlying file is seekable. This allows WSGI + middleware to implement things like range requests for example + + See https://github.com/Pylons/waitress/issues/359 and + https://github.com/Pylons/waitress/pull/363 + - In Python 3 ``OSError`` is no longer subscriptable, this caused failures on Windows attempting to loop to find an socket that would work for use in the trigger.