Tests: add helper for form-data and multipart.
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import io
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
@@ -1223,31 +1224,25 @@ class TestJavaApplication(TestApplicationJava):
|
|||||||
os.mkdir(fulldst)
|
os.mkdir(fulldst)
|
||||||
self.public_dir(fulldst)
|
self.public_dir(fulldst)
|
||||||
|
|
||||||
body = (
|
fields = {
|
||||||
"""Preamble. Should be ignored.\r
|
'file': {
|
||||||
\r
|
'filename': 'sample.txt',
|
||||||
--12345\r
|
'type': 'text/plain',
|
||||||
Content-Disposition: form-data; name="file"; filename="sample.txt"\r
|
'data': io.StringIO('Data from sample file'),
|
||||||
Content-Type: text/plain\r
|
},
|
||||||
\r
|
'destination': fulldst,
|
||||||
Data from sample file\r
|
'upload': 'Upload',
|
||||||
--12345\r
|
}
|
||||||
Content-Disposition: form-data; name="destination"\r
|
|
||||||
\r
|
encoded, content_type = self.multipart_encode(fields)
|
||||||
%s\r
|
|
||||||
--12345\r
|
preamble = 'Preamble. Should be ignored.'
|
||||||
Content-Disposition: form-data; name="upload"\r
|
epilogue = 'Epilogue. Should be ignored.'
|
||||||
\r
|
body = "%s\r\n%s\r\n%s" % (preamble, encoded.decode(), epilogue)
|
||||||
Upload\r
|
|
||||||
--12345--\r
|
|
||||||
\r
|
|
||||||
Epilogue. Should be ignored."""
|
|
||||||
% fulldst
|
|
||||||
)
|
|
||||||
|
|
||||||
resp = self.post(
|
resp = self.post(
|
||||||
headers={
|
headers={
|
||||||
'Content-Type': 'multipart/form-data; boundary=12345',
|
'Content-Type': content_type,
|
||||||
'Host': 'localhost',
|
'Host': 'localhost',
|
||||||
'Connection': 'close',
|
'Connection': 'close',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import binascii
|
||||||
|
import io
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
@@ -68,6 +71,10 @@ class TestHTTP(TestUnit):
|
|||||||
if body != b'':
|
if body != b'':
|
||||||
if isinstance(body, str):
|
if isinstance(body, str):
|
||||||
body = body.encode()
|
body = body.encode()
|
||||||
|
elif isinstance(body, dict):
|
||||||
|
body, content_type = self.form_encode(body)
|
||||||
|
|
||||||
|
headers['Content-Type'] = content_type
|
||||||
|
|
||||||
if 'Content-Length' not in headers:
|
if 'Content-Length' not in headers:
|
||||||
headers['Content-Length'] = len(body)
|
headers['Content-Length'] = len(body)
|
||||||
@@ -266,3 +273,69 @@ class TestHTTP(TestUnit):
|
|||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
self.assertTrue(ret, 'socket connected')
|
self.assertTrue(ret, 'socket connected')
|
||||||
|
|
||||||
|
def form_encode(self, fields):
|
||||||
|
is_multipart = False
|
||||||
|
|
||||||
|
for _, value in fields.items():
|
||||||
|
if isinstance(value, dict):
|
||||||
|
is_multipart = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if is_multipart:
|
||||||
|
body, content_type = self.multipart_encode(fields)
|
||||||
|
|
||||||
|
else:
|
||||||
|
body, content_type = self.form_url_encode(fields)
|
||||||
|
|
||||||
|
return body, content_type
|
||||||
|
|
||||||
|
def form_url_encode(self, fields):
|
||||||
|
data = "&".join("%s=%s" % (name, value)
|
||||||
|
for name, value in fields.items()).encode()
|
||||||
|
return data, 'application/x-www-form-urlencoded'
|
||||||
|
|
||||||
|
def multipart_encode(self, fields):
|
||||||
|
boundary = binascii.hexlify(os.urandom(16)).decode('ascii')
|
||||||
|
|
||||||
|
body = ''
|
||||||
|
|
||||||
|
for field, value in fields.items():
|
||||||
|
filename = ''
|
||||||
|
datatype = ''
|
||||||
|
|
||||||
|
if isinstance(value, dict):
|
||||||
|
datatype = 'text/plain'
|
||||||
|
filename = value['filename']
|
||||||
|
|
||||||
|
if value.get('type'):
|
||||||
|
datatype = value['type']
|
||||||
|
|
||||||
|
if not isinstance(value['data'], io.IOBase):
|
||||||
|
self.fail('multipart encoding of file requires a stream.')
|
||||||
|
|
||||||
|
data = value['data'].read()
|
||||||
|
|
||||||
|
elif isinstance(value, str):
|
||||||
|
data = value
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.fail('multipart requires a string or stream data')
|
||||||
|
|
||||||
|
body += (
|
||||||
|
"--%s\r\nContent-Disposition: form-data; name=\"%s\""
|
||||||
|
) % (boundary, field)
|
||||||
|
|
||||||
|
if filename != '':
|
||||||
|
body += "; filename=\"%s\"" % filename
|
||||||
|
|
||||||
|
body += "\r\n"
|
||||||
|
|
||||||
|
if datatype != '':
|
||||||
|
body += "Content-Type: %s\r\n" % datatype
|
||||||
|
|
||||||
|
body += "\r\n%s\r\n" % data
|
||||||
|
|
||||||
|
body += "--%s--\r\n" % boundary
|
||||||
|
|
||||||
|
return body.encode(), "multipart/form-data; boundary=%s" % boundary
|
||||||
|
|||||||
Reference in New Issue
Block a user