diff --git a/src/nucleus/domains/http/parsers/request.py b/src/nucleus/domains/http/parsers/request.py index a4de165..d01db8c 100644 --- a/src/nucleus/domains/http/parsers/request.py +++ b/src/nucleus/domains/http/parsers/request.py @@ -4,9 +4,41 @@ __email__ = 'remizoffalex@mail.ru' from nucleus.domains.http.models.request import Request -def parse_(raw): - method, uri, protocol = raw.decode().split(' ') - return method, uri,protocol +def urlsplit(url): + result = {} + fragment = url.split('#', 1) + if len(fragment)>1: + result['fragment'] = fragment[1] + no_fragment = fragment[0] + query = no_fragment.split('?', 1) + if len(query)>1: + result['params'] = query[1] + no_query = query[0] + if '://' in no_query: + scheme, no_query = no_query.split('://', 1) + result['scheme'] = scheme + if ':' in no_query: + host, port_path = no_query.split(':', 1) + result['host'] = host + port, path = port_path.split('/', 1) + result['port'] = port + result['path'] = path + else: + result['path'] = no_query + return result + + +def parse_url(raw): + method, url, protocol = raw.decode().split(' ') + result = { + 'method': method, + 'url': url, + 'protocol': protocol + } + segments = urlsplit(url) + for key in segments: + result[key] = segments[key] + return result def parse(raw): @@ -15,7 +47,9 @@ def parse(raw): request.raw = raw parts = raw.split(b'\r\n', 1) headers = parts[0].decode().split(' ') - request.method, request.uri, request.protocol = parse_(parts[0]) + common = parse_url(parts[0]) + for key in common: + setattr(request, key, common[key]) parts_two = parts[1].split(b'\r\n'*2) request.headers = {} for item in parts_two[0].decode().split('\r\n'): diff --git a/tests/test_request.py b/tests/test_request.py new file mode 100644 index 0000000..cb999b2 --- /dev/null +++ b/tests/test_request.py @@ -0,0 +1,32 @@ +__author__ = 'RemiZOffAlex' +__email__ = 'remizoffalex@mail.ru' + +import unittest + +from nucleus.domains.http.models.request import Request + + +raw = b'GET /favicon.ico HTTP/1.1\r\nHost: 10.2.0.1:5000\r\nConnection: keep-alive\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 OPR/123.0.0.0\r\nAccept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8\r\nReferer: http://10.2.0.1:5000/\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: ru,en;q=0.9\r\n\r\n' + + +class TestRequest(unittest.TestCase): + def test_request(self): + request = Request + parts = raw.split(b'\r\n', 1) + request_line = parts[0].decode().split(' ') + request.method = request_line[0] + request.url = request_line[1] + request.protocol = request_line[2] + parts_two = parts[1].split(b'\r\n'*2) + request.headers = {} + for item in parts_two[0].decode().split('\r\n'): + key, value = item.split(': ') + request.headers[key] = value + + self.assertTrue(request.method=='GET') + self.assertTrue(request.url=='/favicon.ico') + self.assertTrue(request.protocol=='HTTP/1.1') + + for key in request.headers: + value = request.headers[key] + print(key, ':', value) diff --git a/tests/test_request_parser.py b/tests/test_request_parser.py new file mode 100644 index 0000000..aa1f5a4 --- /dev/null +++ b/tests/test_request_parser.py @@ -0,0 +1,30 @@ +__author__ = 'RemiZOffAlex' +__email__ = 'remizoffalex@mail.ru' + +import unittest + +from nucleus.domains.http.parsers.request import parse + + +raw = b'GET /page?id=1 HTTP/1.1\r\nHost: 10.2.0.1:5000\r\nConnection: keep-alive\r\nDNT: 1\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: ru,en-US;q=0.9,en;q=0.8\r\n\r\n' + + +class TestRequestParse(unittest.TestCase): + def test_parse_1(self): + request = parse(raw) + print('') + for key in request.__dict__: + print(key, getattr(request, key)) + + self.assertTrue(request.method=='GET') + self.assertTrue(request.url=='/page?id=1') + self.assertTrue(request.path=='/page') + self.assertTrue(request.protocol=='HTTP/1.1') + + headers = request.headers + self.assertTrue(headers['Host']=='10.2.0.1:5000') + self.assertTrue(headers['Connection']=='keep-alive') + self.assertTrue(headers['User-Agent']=='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36') + self.assertTrue(headers['Accept']=='text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7') + self.assertTrue(headers['Accept-Encoding']=='gzip, deflate') + self.assertTrue(headers['Accept-Language']=='ru,en-US;q=0.9,en;q=0.8')