def test_wsgirequest_path_info(self): def wsgi_str(path_info, encoding='utf-8'): path_info = path_info.encode( encoding) # Actual URL sent by the browser (bytestring) path_info = path_info.decode( 'iso-8859-1') # Value in the WSGI environ dict (native string) return path_info # Regression for #19468 request = WSGIRequest({ 'PATH_INFO': wsgi_str("/سلام/"), 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b'') }) self.assertEqual(request.path, "/سلام/") # The URL may be incorrectly encoded in a non-UTF-8 encoding (#26971) request = WSGIRequest({ 'PATH_INFO': wsgi_str("/café/", encoding='iso-8859-1'), 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b''), }) # Since it's impossible to decide the (wrong) encoding of the URL, it's # left percent-encoded in the path. self.assertEqual(request.path, "/caf%E9/")
def setUp(self): payload = FakePayload("\r\n".join(['a=1&a=2;a=3', ''])) self.request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload, })
def test_stream(self): payload = FakePayload('name=value') request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload }) self.assertEqual(request.read(), b'name=value')
def test_set_encoding_clears_GET(self): request = WSGIRequest({ 'REQUEST_METHOD': 'GET', 'wsgi.input': '', 'QUERY_STRING': 'name=Hello%20G%C3%BCnter', }) self.assertEqual(request.GET, {'name': ['Hello Günter']}) request.encoding = 'iso-8859-16' self.assertEqual(request.GET, {'name': ['Hello G\u0102\u0152nter']})
def test_set_encoding_clears_POST(self): payload = FakePayload('name=Hello Günter') request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload, }) self.assertEqual(request.POST, {'name': ['Hello Günter']}) request.encoding = 'iso-8859-16' self.assertEqual(request.POST, {'name': ['Hello GĂŒnter']})
def setUp(self): payload = FakePayload("\r\n".join([ '--boundary', 'Content-Disposition: form-data; name="name"', '', 'value', '--boundary--' '' ])) self.request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'multipart/form-data; boundary=boundary', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload, })
def test_set_encoding_clears_POST(self): for method in HTTP_METHODS_WITH_BODY: payload = FakePayload('{"name": "佚名"}') request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/json', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload, }) self.assertEqual(request.data, {'name': '佚名'}) request.encoding = 'GBK' self.assertEqual(request.POST, {'name': '浣氬悕'})
def test_POST_after_body_read_and_stream_read(self): """ POST should be populated even if body is read first, and then the stream is read second. """ payload = FakePayload('name=value') request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload, }) request.body # evaluate self.assertEqual(request.read(1), b'n') self.assertEqual(request.POST, {'name': ['value']})
def test_read_after_value(self): """ Reading from request is allowed after accessing request contents as POST or body. """ payload = FakePayload('name=value') request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload, }) self.assertEqual(request.POST, {'name': ['value']}) self.assertEqual(request.body, b'name=value') self.assertEqual(request.read(), b'name=value')
def test_read_after_value(self): """ Reading from request is allowed after accessing request contents as data or body. """ for method in HTTP_METHODS_WITH_BODY: payload = FakePayload('{"name": "value"}') request = WSGIRequest({ 'REQUEST_METHOD': method, 'CONTENT_TYPE': 'application/json', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload }) self.assertEqual(request.data, {'name': 'value'}) self.assertEqual(request.body, b'{"name": "value"}') self.assertEqual(request.read(), b'{"name": "value"}')
def test_value_after_read(self): """ Construction of POST or body is not allowed after reading from request. """ payload = FakePayload('name=value') request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload, }) self.assertEqual(request.read(2), b'na') with self.assertRaises(RawPostDataException): request.body self.assertEqual(request.POST, {})
def test_file_passes(self): payload = FakePayload("\r\n".join([ '--boundary', 'Content-Disposition: form-data; name="file1"; filename="test.file"', '', 'value', '--boundary--' '' ])) request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'multipart/form-data; boundary=boundary', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload, }) with self.settings(DATA_UPLOAD_MAX_MEMORY_SIZE=1): request._load_post_and_files() self.assertIn('file1', request.FILES, "Upload file not present")
def test_value_after_read(self): """ Construction of POST or body is not allowed after reading from request. """ for method in HTTP_METHODS_WITH_BODY: payload = FakePayload('{"name": "value"}') request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/json', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload }) self.assertEqual(request.read(2), b'{"') with self.assertRaises(RawPostDataException): request.body self.assertEqual(request.data, {})
def test_get_max_fields_not_exceeded(self): with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=3): request = WSGIRequest({ 'REQUEST_METHOD': 'GET', 'wsgi.input': BytesIO(b''), 'QUERY_STRING': 'a=1&a=2;a=3', }) request.GET['a']
def test_POST_after_body_read_and_stream_read(self): """ POST should be populated even if body is read first, and then the stream is read second. """ for method in HTTP_METHODS_WITH_BODY: payload = FakePayload('{"name": "佚名"}') request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/json', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload }) request.body # evaluate self.assertEqual(request.read(1), b'{') self.assertEqual(request.POST, {'name': '佚名'}) self.assertEqual(request.data, {'name': '佚名'})
def test_wsgi_request_headers_get(self): request = WSGIRequest(self.ENVIRON) self.assertEqual(request.headers.get('User-Agent'), 'python-requests/1.2.0') self.assertEqual(request.headers.get('user-agent'), 'python-requests/1.2.0') self.assertEqual(request.headers.get('Content-Type'), 'text/html') self.assertEqual(request.headers.get('Content-Length'), '100')
def test_read_by_lines(self): payload = FakePayload('name=value') request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload, }) self.assertEqual(list(request), [b'name=value'])
def test_non_ascii_POST(self): payload = FakePayload(urlencode({'key': 'España'})) request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_LENGTH': len(payload), 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'wsgi.input': payload, }) self.assertEqual(request.POST, {'key': ['España']})
def test_wsgi_request_headers(self): request = WSGIRequest(self.ENVIRON) self.assertEqual( dict(request.headers), { 'Content-Type': 'text/html', 'Content-Length': '100', 'Accept': '*', 'Host': 'example.com', 'User-Agent': 'python-requests/1.2.0', })
def test_multipart_non_ascii_content_type(self): request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'multipart/form-data; boundary = \xe0', 'CONTENT_LENGTH': 0, 'wsgi.input': FakePayload(), }) msg = 'Invalid non-ASCII Content-Type in multipart: multipart/form-data; boundary = à' with self.assertRaisesMessage(MultiPartParserError, msg): request.POST
def test_multipart_without_boundary(self): request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'multipart/form-data;', 'CONTENT_LENGTH': 0, 'wsgi.input': FakePayload(), }) with self.assertRaisesMessage(MultiPartParserError, 'Invalid boundary in multipart: None'): request.POST
def test_POST_binary_only(self): payload = b'\r\n\x01\x00\x00\x00ab\x00\x00\xcd\xcc,@' environ = { 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'application/octet-stream', 'CONTENT_LENGTH': len(payload), 'wsgi.input': BytesIO(payload), } request = WSGIRequest(environ) self.assertEqual(request.POST, {}) self.assertEqual(request.FILES, {}) self.assertEqual(request.body, payload) # Same test without specifying content-type environ.update({'CONTENT_TYPE': '', 'wsgi.input': BytesIO(payload)}) request = WSGIRequest(environ) self.assertEqual(request.POST, {}) self.assertEqual(request.FILES, {}) self.assertEqual(request.body, payload)
def test_get_max_fields_exceeded(self): with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=1): with self.assertRaisesMessage(TooManyFieldsSent, TOO_MANY_FIELDS_MSG): request = WSGIRequest({ 'REQUEST_METHOD': 'GET', 'wsgi.input': BytesIO(b''), 'QUERY_STRING': 'a=1&a=2;a=3', }) request.GET['a']
def test_non_ascii_POST(self): for method in HTTP_METHODS_WITH_BODY: payload = FakePayload('{"name": "佚名"}') request = WSGIRequest({ 'REQUEST_METHOD': method, 'CONTENT_LENGTH': len(payload), 'CONTENT_TYPE': 'application/json', 'wsgi.input': payload, }) self.assertEqual(request.data, {'name': '佚名'})
def test_POST_after_body_read_and_stream_read_multipart(self): """ POST should be populated even if body is read first, and then the stream is read second. Using multipart/form-data instead of urlencoded. """ payload = FakePayload("\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': payload, }) request.body # evaluate # Consume enough data to mess up the parsing: self.assertEqual(request.read(13), b'--boundary\r\nC') self.assertEqual(request.POST, {'name': ['value']})
def test_wsgirequest_path_with_force_script_name_trailing_slash(self): """ The request's path is correctly assembled, regardless of whether or not the FORCE_SCRIPT_NAME setting has a trailing slash (#20169). """ # With trailing slash with override_settings(FORCE_SCRIPT_NAME='/FORCED_PREFIX/'): request = WSGIRequest({ 'PATH_INFO': '/somepath/', 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b'') }) self.assertEqual(request.path, '/FORCED_PREFIX/somepath/') # Without trailing slash with override_settings(FORCE_SCRIPT_NAME='/FORCED_PREFIX'): request = WSGIRequest({ 'PATH_INFO': '/somepath/', 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b'') }) self.assertEqual(request.path, '/FORCED_PREFIX/somepath/')
def test_wsgirequest_with_script_name(self): """ The request's path is correctly assembled, regardless of whether or not the SCRIPT_NAME has a trailing slash (#20169). """ # With trailing slash request = WSGIRequest({ 'PATH_INFO': '/somepath/', 'SCRIPT_NAME': '/PREFIX/', 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b''), }) self.assertEqual(request.path, '/PREFIX/somepath/') # Without trailing slash request = WSGIRequest({ 'PATH_INFO': '/somepath/', 'SCRIPT_NAME': '/PREFIX', 'REQUEST_METHOD': 'get', 'wsgi.input': BytesIO(b''), }) self.assertEqual(request.path, '/PREFIX/somepath/')
class DataUploadMaxNumberOfFieldsMultipartPost(SimpleTestCase): def setUp(self): payload = FakePayload("\r\n".join([ '--boundary', 'Content-Disposition: form-data; name="name1"', '', 'value1', '--boundary', 'Content-Disposition: form-data; name="name2"', '', 'value2', '--boundary--' '' ])) self.request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'multipart/form-data; boundary=boundary', 'CONTENT_LENGTH': len(payload), 'wsgi.input': payload, }) def test_number_exceeded(self): with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=1): with self.assertRaisesMessage(TooManyFieldsSent, TOO_MANY_FIELDS_MSG): self.request._load_post_and_files() def test_number_not_exceeded(self): with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=2): self.request._load_post_and_files() def test_no_limit(self): with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=None): self.request._load_post_and_files()
def test_alternate_charset_POST(self): """ Test a POST with non-utf-8 payload encoding. """ payload = FakePayload(urlencode({'key': 'España'.encode('latin-1')})) request = WSGIRequest({ 'REQUEST_METHOD': 'POST', 'CONTENT_LENGTH': len(payload), 'CONTENT_TYPE': 'application/x-www-form-urlencoded; charset=iso-8859-1', 'wsgi.input': payload, }) self.assertEqual(request.POST, {'key': ['España']})
def test_alternate_charset_POST(self): """ Test a POST with non-utf-8 payload encoding. """ for method in HTTP_METHODS_WITH_BODY: payload = FakePayload('{"name": "佚名"}'.encode('GBK')) request = WSGIRequest({ 'REQUEST_METHOD': method, 'CONTENT_LENGTH': len(payload), 'CONTENT_TYPE': 'application/json; charset=GBK', 'wsgi.input': payload, }) self.assertEqual(request.data, {'name': '佚名'})