Commit 0f1d8afe authored by Jérome Perrin's avatar Jérome Perrin

recipe/simplehttpserver: fix application/x-www-form-urlencoded POST on py3

In deploy test, this recipe is used with url encoded POST [1], but the
test only tested multipart encoded POSTs. In python 3, they are different,
with multipart POSTs, FieldStorage values are bytes, but with url encoded
POSTs, the values are string.

This small server from the recipe only supported multipart POSTs, this
change add support for url encoded POSTs.

[1]: https://lab.nexedi.com/nexedi/slapos/blob/dd7038feab70866e54028de89d0e0e1017fc276c/software/erp5testnode/testsuite/deploy-test/deploy-script-controller#L86
parent 4dcf80d4
......@@ -36,6 +36,15 @@ class ServerHandler(SimpleHTTPRequestHandler):
SimpleHTTPRequestHandler.do_GET(self)
def do_POST(self):
"""Write to a file on the server.
request keys:
path: the path of the file
content: content of the file
clear: (0|1 default 1) overwrite the file if 1
request can be encoded as application/x-www-form-urlencoded or multipart/form-data
"""
logging.info('%s - POST: %s \n%s' % (self.client_address[0], self.path, self.headers))
if self.restrictedRootAccess():
return
......@@ -46,14 +55,20 @@ class ServerHandler(SimpleHTTPRequestHandler):
environ={'REQUEST_METHOD': 'POST',
'CONTENT_TYPE': self.headers['Content-Type']}
)
name = form['path'].value.decode('utf-8')
content = form['content'].value
method = 'ab'
if 'clear' in form and form['clear'].value == '1':
method = 'wb'
self.writeFile(name, content, method)
file_content = form['content'].value
file_path = form['path'].value
if form['content'].file:
# post data as multipart/form-data , values are bytes
file_path = file_path.decode('utf-8')
else:
# application/x-www-form-urlencoded , values are str
file_content = file_content.encode('utf-8')
file_open_mode = 'wb' if ('clear' in form and form['clear'].value in ('1', b'1')) else 'ab'
self.writeFile(file_path, file_content, file_open_mode)
self.respond(200, type=self.headers['Content-Type'])
self.wfile.write(b"Content written to %s" % str2bytes(name))
self.wfile.write(b"Content written to %s" % str2bytes(file_path))
def writeFile(self, filename, content, method='ab'):
file_path = os.path.abspath(os.path.join(self.document_path, filename))
......
......@@ -71,22 +71,43 @@ class SimpleHTTPServerTest(unittest.TestCase):
'server did not start.\nout: %s error: %s' % self.process.communicate())
self.assertIn('Directory listing for /', resp.text)
# post with multipart/form-data encoding
resp = requests.post(
server_base_url,
files={
'path': 'hello.txt',
'content': b'hello',
'path': 'hello-form-data.txt',
'content': 'hello-form-data',
},
)
self.assertEqual(resp.status_code, requests.codes.ok)
self.assertEqual(resp.text, 'Content written to hello-form-data.txt')
with open(
os.path.join(self.base_path, self.recipe.options['path'],
'hello.txt')) as f:
self.assertEqual(f.read(), 'hello')
'hello-form-data.txt')) as f:
self.assertEqual(f.read(), 'hello-form-data')
self.assertIn('hello.txt', requests.get(server_base_url).text)
self.assertIn('hello-form-data.txt', requests.get(server_base_url).text)
self.assertEqual(
requests.get(server_base_url + '/hello.txt').text, 'hello')
requests.get(server_base_url + '/hello-form-data.txt').text, 'hello-form-data')
# post as application/x-www-form-urlencoded
resp = requests.post(
server_base_url,
data={
'path': 'hello-form-urlencoded.txt',
'content': 'hello-form-urlencoded',
},
)
self.assertEqual(resp.status_code, requests.codes.ok)
with open(
os.path.join(self.base_path, self.recipe.options['path'],
'hello-form-urlencoded.txt')) as f:
self.assertEqual(f.read(), 'hello-form-urlencoded')
self.assertIn('hello-form-urlencoded.txt', requests.get(server_base_url).text)
self.assertEqual(resp.text, 'Content written to hello-form-urlencoded.txt')
self.assertEqual(
requests.get(server_base_url + '/hello-form-urlencoded.txt').text, 'hello-form-urlencoded')
# incorrect paths are refused
for path in '/hello.txt', '../hello.txt':
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment