summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2022-01-17 17:26:45 -0600
committerGitHub <noreply@github.com>2022-01-17 17:26:45 -0600
commite828cd5731e18b6e884772057ada47a15538143a (patch)
tree2a3ba58271e29785055b4862eb085a3c04d5f738
parent88d5e7bfd48059c32ea37fff3af91234eedf9524 (diff)
parent5627a4c322ae02c79bb61e531fc6bf8e0a69c9b8 (diff)
downloadwaitress-e828cd5731e18b6e884772057ada47a15538143a.tar.gz
Merge pull request #363 from Pylons/bugfix/wsgi-file-wrapper
Bugfix: wsgi.file_wrapper should pass-through seek/tell attrs
-rw-r--r--CHANGES.txt7
-rw-r--r--src/waitress/buffers.py10
-rw-r--r--tests/test_buffers.py4
3 files changed, 21 insertions, 0 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 5ccaa64..888c31b 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.
diff --git a/src/waitress/buffers.py b/src/waitress/buffers.py
index 386eb40..8091ff0 100644
--- a/src/waitress/buffers.py
+++ b/src/waitress/buffers.py
@@ -145,6 +145,16 @@ class ReadOnlyFileBasedBuffer(FileBasedBuffer):
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()
diff --git a/tests/test_buffers.py b/tests/test_buffers.py
index 01cdc2d..b37949b 100644
--- a/tests/test_buffers.py
+++ b/tests/test_buffers.py
@@ -185,6 +185,8 @@ class TestReadOnlyFileBasedBuffer(unittest.TestCase):
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 @@ class TestReadOnlyFileBasedBuffer(unittest.TestCase):
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)