Skip to content

Commit 36dd749

Browse files
committed
Fix regression with FieldStorage and large payloads (#15)
1 parent 3b573aa commit 36dd749

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

webware/WebUtils/FieldStorage.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,8 @@ def read_binary(self):
435435
data = data.decode()
436436
except UnicodeDecodeError:
437437
self._binary_file = True
438-
self.file = self.make_file()
438+
if self.file is None:
439+
self.file = self.make_file()
439440
self.file.write(data)
440441
todo -= len(data)
441442

webware/WebUtils/Tests/TestFieldStorageModified.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,86 @@ def testPostRequestWithNonUtf8TextData(self):
257257
self.assertEqual(fs.bytes_read, length)
258258
self.assertEqual(fs.file.read(), content)
259259

260+
def testPostRequestWithSmallPayloadWithContentLength(self):
261+
length = 1000 # much smaller than buffer size
262+
payload = 'x' * length
263+
fs = FieldStorage(
264+
fp=BytesIO(payload.encode()),
265+
environ={'REQUEST_METHOD': 'POST',
266+
'CONTENT_TYPE': 'text/plain',
267+
'CONTENT_LENGTH': length})
268+
self.assertEqual(fs.headers, {
269+
'content-type': 'text/plain',
270+
'content-length': length})
271+
self.assertEqual(fs.type, 'text/plain')
272+
self.assertEqual(fs.length, length)
273+
self.assertEqual(fs.bytes_read, length)
274+
self.assertEqual(fs.file.read(), payload)
275+
276+
def testPostRequestWithLargeTextPayloadWithContentLength(self):
277+
length = 25000 # much larger than buffer size
278+
payload = 'x' * length
279+
fs = FieldStorage(
280+
fp=BytesIO(payload.encode()),
281+
environ={'REQUEST_METHOD': 'POST',
282+
'CONTENT_TYPE': 'text/plain',
283+
'CONTENT_LENGTH': length})
284+
self.assertEqual(fs.headers, {
285+
'content-type': 'text/plain',
286+
'content-length': length})
287+
self.assertEqual(fs.type, 'text/plain')
288+
self.assertEqual(fs.length, length)
289+
self.assertEqual(fs.bytes_read, length)
290+
self.assertEqual(fs.file.read(), payload)
291+
292+
def testPostRequestWithLargeJsonPayloadWithContentLength(self):
293+
# create JSON payload that is much larger than the buffer size
294+
payload = {f'test{i}': str(i) * 5000 for i in range(5)}
295+
payload = str(payload).replace("'", '"')
296+
length = len(payload)
297+
self.assertGreater(length, 25000)
298+
fs = FieldStorage(
299+
fp=BytesIO(payload.encode()),
300+
environ={'REQUEST_METHOD': 'POST',
301+
'CONTENT_TYPE': 'application/json',
302+
'CONTENT_LENGTH': length})
303+
self.assertEqual(fs.headers, {
304+
'content-type': 'application/json',
305+
'content-length': length})
306+
self.assertEqual(fs.type, 'application/json')
307+
self.assertEqual(fs.length, length)
308+
self.assertEqual(fs.bytes_read, length)
309+
# make sure that the original payload is preserved
310+
self.assertEqual(fs.file.read(), payload)
311+
312+
def testPostRequestWithSmallPayloadWithoutContentLength(self):
313+
length = 1000 # much smaller than buffer size
314+
payload = 'x' * length
315+
fs = FieldStorage(
316+
fp=BytesIO(payload.encode()),
317+
environ={'REQUEST_METHOD': 'POST',
318+
'CONTENT_TYPE': 'text/plain'})
319+
self.assertEqual(fs.headers, {
320+
'content-type': 'text/plain'})
321+
self.assertEqual(fs.type, 'text/plain')
322+
self.assertEqual(fs.length, -1)
323+
self.assertEqual(fs.bytes_read, length)
324+
self.assertEqual(fs.file.read(), payload)
325+
326+
def testPostRequestWithLargePayloadWithoutContentLength(self):
327+
length = 25000 # much larger than buffer size
328+
payload = 'x' * length
329+
fs = FieldStorage(
330+
fp=BytesIO(payload.encode()),
331+
environ={'REQUEST_METHOD': 'POST',
332+
'CONTENT_TYPE': 'text/plain'})
333+
self.assertEqual(fs.headers, {
334+
'content-type': 'text/plain'})
335+
self.assertEqual(fs.type, 'text/plain')
336+
self.assertEqual(fs.length, -1)
337+
self.assertEqual(fs.bytes_read, length)
338+
self.assertEqual(fs.file.read(), payload)
339+
260340
def testIsBinaryType(self):
261341
self.assertIs(isBinaryType('application/json'), False)
262342
self.assertIs(isBinaryType('application/xml'), False)

0 commit comments

Comments
 (0)