summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Bicking <ian@ianbicking.org>2007-10-10 01:17:23 +0000
committerIan Bicking <ian@ianbicking.org>2007-10-10 01:17:23 +0000
commit054e427ff60c5793494b8fee7931b00ab952d4b3 (patch)
tree4d4135cb96c062a16deedfff1297b211dd694850
parent747299cd96382521f25223c171acca457fb1b081 (diff)
downloadpaste-git-054e427ff60c5793494b8fee7931b00ab952d4b3.tar.gz
Fix #194, paste.cascade doesn't copy wsgi.input, and blocking can occur: now wsgi.input is copied and .seek(0) on each call
-rw-r--r--docs/news.txt4
-rw-r--r--paste/cascade.py21
2 files changed, 25 insertions, 0 deletions
diff --git a/docs/news.txt b/docs/news.txt
index 2c4da0c..f95eda9 100644
--- a/docs/news.txt
+++ b/docs/news.txt
@@ -23,6 +23,10 @@ svn trunk
* ``paste.httpexceptions.HTTPExceptionHandler`` will no longer catch
exceptions raised during the app_iter iteration.
+* ``paste.cascade.Cascade`` copies ``wsgi.input`` when cascading, so
+ that one of the applications cannot read the input and leave a later
+ application blocked when it tries to read the input.
+
* Fix assigning to ``WSGIResponse.charset`` breaking the content-type.
1.4.2
diff --git a/paste/cascade.py b/paste/cascade.py
index 9176320..962da31 100644
--- a/paste/cascade.py
+++ b/paste/cascade.py
@@ -7,6 +7,8 @@ return ``404 Not Found``.
"""
from paste import httpexceptions
from paste.util import converters
+import tempfile
+from cStringIO import StringIO
__all__ = ['Cascade']
@@ -74,8 +76,27 @@ class Cascade(object):
return _consuming_writer
return start_response(status, headers, exc_info)
+ length = int(environ.get('CONTENT_LENGTH', '0'))
+ if length > 0:
+ # We have to copy wsgi.input
+ copy_wsgi_input = True
+ if length > 4096 or length == -1:
+ f = tempfile.TemporaryFile()
+ copy_len = length
+ while copy_len:
+ chunk = environ['wsgi.input'].read(min(copy_len, 4096))
+ f.write(chunk)
+ copy_len -= len(chunk)
+ f.seek(0)
+ else:
+ f = StringIO(environ['wsgi.input'].read(length))
+ environ['wsgi.input'] = f
+ else:
+ copy_wsgi_input = False
for app in self.apps[:-1]:
environ_copy = environ.copy()
+ if copy_wsgi_input:
+ environ_copy['wsgi.input'].seek(0)
failed = []
try:
v = app(environ_copy, repl_start_response)