mirror of https://github.com/django/django.git
Fixed #15679 - regression in HttpRequest.POST and raw_post_data access.
Thanks to vkryachko for the report. This also fixes a slight inconsistency with raw_post_data after parsing of a multipart request, and adds a test for that. (Previously accessing raw_post_data would have returned the empty string rather than raising an Exception). git-svn-id: http://code.djangoproject.com/svn/django/trunk@15938 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
728770a5f9
commit
8bb46d8b7c
|
@ -262,14 +262,18 @@ class HttpRequest(object):
|
||||||
if self.method != 'POST':
|
if self.method != 'POST':
|
||||||
self._post, self._files = QueryDict('', encoding=self._encoding), MultiValueDict()
|
self._post, self._files = QueryDict('', encoding=self._encoding), MultiValueDict()
|
||||||
return
|
return
|
||||||
if self._read_started:
|
if self._read_started and not hasattr(self, '_raw_post_data'):
|
||||||
self._mark_post_parse_error()
|
self._mark_post_parse_error()
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.META.get('CONTENT_TYPE', '').startswith('multipart'):
|
if self.META.get('CONTENT_TYPE', '').startswith('multipart'):
|
||||||
self._raw_post_data = ''
|
if hasattr(self, '_raw_post_data'):
|
||||||
|
# Use already read data
|
||||||
|
data = StringIO(self._raw_post_data)
|
||||||
|
else:
|
||||||
|
data = self
|
||||||
try:
|
try:
|
||||||
self._post, self._files = self.parse_file_upload(self.META, self)
|
self._post, self._files = self.parse_file_upload(self.META, data)
|
||||||
except:
|
except:
|
||||||
# An error occured while parsing POST data. Since when
|
# An error occured while parsing POST data. Since when
|
||||||
# formatting the error the request handler might access
|
# formatting the error the request handler might access
|
||||||
|
|
|
@ -179,6 +179,66 @@ class RequestsTests(unittest.TestCase):
|
||||||
self.assertRaises(Exception, lambda: request.raw_post_data)
|
self.assertRaises(Exception, lambda: request.raw_post_data)
|
||||||
self.assertEqual(request.POST, {})
|
self.assertEqual(request.POST, {})
|
||||||
|
|
||||||
|
def test_raw_post_data_after_POST_multipart(self):
|
||||||
|
"""
|
||||||
|
Reading raw_post_data after parsing multipart is not allowed
|
||||||
|
"""
|
||||||
|
# Because multipart is used for large amounts fo data i.e. file uploads,
|
||||||
|
# we don't want the data held in memory twice, and we don't want to
|
||||||
|
# silence the error by setting raw_post_data = '' either.
|
||||||
|
payload = "\r\n".join([
|
||||||
|
'--boundary',
|
||||||
|
'Content-Disposition: form-data; name="name"',
|
||||||
|
'',
|
||||||
|
'value',
|
||||||
|
'--boundary--'
|
||||||
|
''])
|
||||||
|
request = WSGIRequest({'REQUEST_METHOD': 'POST',
|
||||||
|
'CONTENT_TYPE': 'multipart/form-data; boundary=boundary',
|
||||||
|
'CONTENT_LENGTH': len(payload),
|
||||||
|
'wsgi.input': StringIO(payload)})
|
||||||
|
self.assertEqual(request.POST, {u'name': [u'value']})
|
||||||
|
self.assertRaises(Exception, lambda: request.raw_post_data)
|
||||||
|
|
||||||
def test_read_by_lines(self):
|
def test_read_by_lines(self):
|
||||||
request = WSGIRequest({'REQUEST_METHOD': 'POST', 'wsgi.input': StringIO('name=value')})
|
request = WSGIRequest({'REQUEST_METHOD': 'POST', 'wsgi.input': StringIO('name=value')})
|
||||||
self.assertEqual(list(request), ['name=value'])
|
self.assertEqual(list(request), ['name=value'])
|
||||||
|
|
||||||
|
def test_POST_after_raw_post_data_read(self):
|
||||||
|
"""
|
||||||
|
POST should be populated even if raw_post_data is read first
|
||||||
|
"""
|
||||||
|
request = WSGIRequest({'REQUEST_METHOD': 'POST', 'wsgi.input': StringIO('name=value')})
|
||||||
|
raw_data = request.raw_post_data
|
||||||
|
self.assertEqual(request.POST, {u'name': [u'value']})
|
||||||
|
|
||||||
|
def test_POST_after_raw_post_data_read_and_stream_read(self):
|
||||||
|
"""
|
||||||
|
POST should be populated even if raw_post_data is read first, and then
|
||||||
|
the stream is read second.
|
||||||
|
"""
|
||||||
|
request = WSGIRequest({'REQUEST_METHOD': 'POST', 'wsgi.input': StringIO('name=value')})
|
||||||
|
raw_data = request.raw_post_data
|
||||||
|
self.assertEqual(request.read(1), u'n')
|
||||||
|
self.assertEqual(request.POST, {u'name': [u'value']})
|
||||||
|
|
||||||
|
def test_POST_after_raw_post_data_read_and_stream_read_multipart(self):
|
||||||
|
"""
|
||||||
|
POST should be populated even if raw_post_data is read first, and then
|
||||||
|
the stream is read second. Using multipart/form-data instead of urlencoded.
|
||||||
|
"""
|
||||||
|
payload = "\r\n".join([
|
||||||
|
'--boundary',
|
||||||
|
'Content-Disposition: form-data; name="name"',
|
||||||
|
'',
|
||||||
|
'value',
|
||||||
|
'--boundary--'
|
||||||
|
''])
|
||||||
|
request = WSGIRequest({'REQUEST_METHOD': 'POST',
|
||||||
|
'CONTENT_TYPE': 'multipart/form-data; boundary=boundary',
|
||||||
|
'CONTENT_LENGTH': len(payload),
|
||||||
|
'wsgi.input': StringIO(payload)})
|
||||||
|
raw_data = request.raw_post_data
|
||||||
|
# Consume enough data to mess up the parsing:
|
||||||
|
self.assertEqual(request.read(13), u'--boundary\r\nC')
|
||||||
|
self.assertEqual(request.POST, {u'name': [u'value']})
|
||||||
|
|
Loading…
Reference in New Issue