diff --git a/matemat/webserver/test/test_post.py b/matemat/webserver/test/test_post.py index 720baea..059d41b 100644 --- a/matemat/webserver/test/test_post.py +++ b/matemat/webserver/test/test_post.py @@ -1,8 +1,6 @@ from typing import Any, Dict, List -import os -import os.path from matemat.webserver.httpd import HttpHandler from matemat.webserver.test.abstract_httpd_test import AbstractHttpdTest, test_pagelet @@ -13,9 +11,13 @@ def post_test_pagelet(method: str, args: Dict[str, str], session_vars: Dict[str, Any], headers: Dict[str, str]): + """ + Test pagelet that simply prints the parsed arguments as response body. + """ + headers['Content-Type'] = 'text/plain' dump: str = '' for k, v in args.items(): - dump += f'{k}: {v}\n' + dump += f'{k}: {v if v is str else ",".join(v)}\n' return 200, dump @@ -24,53 +26,140 @@ class TestPost(AbstractHttpdTest): Test cases for the content serving of the web server. """ - def setUp(self): - super().setUp() - # Create a static resource in the temp dir - with open(os.path.join(self.tempdir.name, 'static_resource.txt'), 'w') as f: - f.write('static resource test') - def test_post_get_only_args(self): + """ + Test a POST request that only contains GET arguments. + """ + # Send POST request self.client_sock.set_request(b'POST /just/testing/post?foo=bar&test=1 HTTP/1.1\r\n' b'Content-Length: 0\r\n' b'Content-Type: application/x-www-form-urlencoded\r\n\r\n') HttpHandler(self.client_sock, ('::1', 45678), self.server) packet = self.client_sock.get_response() + + # Parse response body lines: List[str] = packet.body.split('\n')[:-1] kv: Dict[str, str] = dict() for l in lines: k, v = l.split(':', 1) - kv[k.strip()] = v.strip() + kv[k.strip()] = v.strip() if ',' not in v else v.strip().split(',') + + # Make sure the arguments were properly parsed self.assertEqual('bar', kv['foo']) self.assertEqual('1', kv['test']) def test_post_post_only_args(self): + """ + Test a POST request that only contains POST arguments (urlencoded). + """ + # Send POST request self.client_sock.set_request(b'POST /just/testing/post HTTP/1.1\r\n' b'Content-Type: application/x-www-form-urlencoded\r\n' b'Content-Length: 14\r\n\r\n' b'foo=bar&test=1\r\n') HttpHandler(self.client_sock, ('::1', 45678), self.server) packet = self.client_sock.get_response() + + # Parse response body lines: List[str] = packet.body.split('\n')[:-1] kv: Dict[str, str] = dict() for l in lines: k, v = l.split(':', 1) - kv[k.strip()] = v.strip() + kv[k.strip()] = v.strip() if ',' not in v else v.strip().split(',') + + # Make sure the arguments were properly parsed self.assertEqual('bar', kv['foo']) self.assertEqual('1', kv['test']) def test_post_mixed_args(self): + """ + Test that mixed POST and GET args are properly parsed, and that POST takes precedence over GET. + """ + # Send POST request self.client_sock.set_request(b'POST /just/testing/post?gettest=1&foo=baz HTTP/1.1\r\n' b'Content-Type: application/x-www-form-urlencoded\r\n' b'Content-Length: 18\r\n\r\n' b'foo=bar&posttest=2\r\n') HttpHandler(self.client_sock, ('::1', 45678), self.server) packet = self.client_sock.get_response() + + # Parse response body lines: List[str] = packet.body.split('\n')[:-1] kv: Dict[str, str] = dict() for l in lines: k, v = l.split(':', 1) - kv[k.strip()] = v.strip() + kv[k.strip()] = v.strip() if ',' not in v else v.strip().split(',') + + # Make sure the arguments were properly parsed self.assertEqual('bar', kv['foo']) self.assertEqual('1', kv['gettest']) self.assertEqual('2', kv['posttest']) + + def test_post_get_array(self): + """ + Test a POST request that contains GET array arguments. + """ + # Send POST request + self.client_sock.set_request(b'POST /just/testing/post?foo=bar&test=1&foo=baz HTTP/1.1\r\n' + b'Content-Length: 0\r\n' + b'Content-Type: application/x-www-form-urlencoded\r\n\r\n') + HttpHandler(self.client_sock, ('::1', 45678), self.server) + packet = self.client_sock.get_response() + + # Parse response body + lines: List[str] = packet.body.split('\n')[:-1] + kv: Dict[str, str] = dict() + for l in lines: + k, v = l.split(':', 1) + kv[k.strip()] = v.strip() if ',' not in v else v.strip().split(',') + + # Make sure the arguments were properly parsed + self.assertListEqual(['bar', 'baz'], kv['foo']) + self.assertEqual('1', kv['test']) + + def test_post_post_array(self): + """ + Test a POST request that contains POST array arguments. + """ + # Send POST request + self.client_sock.set_request(b'POST /just/testing/post HTTP/1.1\r\n' + b'Content-Length: 22\r\n' + b'Content-Type: application/x-www-form-urlencoded\r\n\r\n' + b'foo=bar&test=1&foo=baz\r\n') + HttpHandler(self.client_sock, ('::1', 45678), self.server) + packet = self.client_sock.get_response() + + # Parse response body + lines: List[str] = packet.body.split('\n')[:-1] + kv: Dict[str, str] = dict() + for l in lines: + k, v = l.split(':', 1) + kv[k.strip()] = v.strip() if ',' not in v else v.strip().split(',') + + # Make sure the arguments were properly parsed + self.assertListEqual(['bar', 'baz'], kv['foo']) + self.assertEqual('1', kv['test']) + + def test_post_mixed_array(self): + """ + Test a POST request that contains both GET and POST array arguments. + """ + # Send POST request + self.client_sock.set_request(b'POST /just/testing/post?foo=getbar&gettest=1&gettest=42&foo=getbaz HTTP/1.1\r\n' + b'Content-Length: 45\r\n' + b'Content-Type: application/x-www-form-urlencoded\r\n\r\n' + b'foo=postbar&posttest=1&posttest=2&foo=postbaz\r\n') + HttpHandler(self.client_sock, ('::1', 45678), self.server) + packet = self.client_sock.get_response() + + # Parse response body + lines: List[str] = packet.body.split('\n')[:-1] + kv: Dict[str, str] = dict() + for l in lines: + k, v = l.split(':', 1) + kv[k.strip()] = v.strip() if ',' not in v else v.strip().split(',') + + # Make sure the arguments were properly parsed + self.assertListEqual(['postbar', 'postbaz'], kv['foo']) + self.assertListEqual(['1', '42'], kv['gettest']) + self.assertListEqual(['1', '2'], kv['posttest'])