import re from time import strftime, gmtime _URI_RESERVED = { '21': '!', '23': '#', '24': '$', '26': '&', '27': '\'', '28': '(', '29': ')', '2A': '*', '2B': '+', '2C': ',', '2F': '/', '3A': ':', '3B': ';', '3D': '=', '3F': '?', '40': '@', '5B': '[', '5D': ']' } BAD_REQUEST = 'HTTP/1.1 400 Bad Request' NOT_FOUND = 'HTTP/1.1 404 Not Found' SUCCESS = 'HTTP/1.1 200 OK' METHOD_NOT_ALLOWED = 'HTTP/1.1 405 Method Not Allowed' def add_headers(status, html: str): return '\r\n'.join([ status, f'Date: {strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime())}', 'Server: BrandNewServer', 'Content-Type: text/html; charset=utf-8', 'Connection: keep-alive', '', html ]) def validate_url(url): url_pattern = re.compile(r'/((.*?/?)+)?') return bool(url_pattern.fullmatch(url)) def parse_cookies(cookies_line: str): cookies_line = cookies_line.strip().strip(';') pairs = cookies_line.split(';') d = {} for pair in pairs: try: key, value = pair.split('=', maxsplit=1) d[key] = value except ValueError: raise ValueError('Wrong format of cookies') return d def parse_headers(request_line: str): request = request_line.split('\r\n') method, url, http_ver = request.pop(0).split() headers = {} for line in request: field, value = line.split(': ', maxsplit=1) headers[field] = value return method, url, http_ver, headers def parse_query(query_line: str): pairs = query_line.strip().split('&') d = {} for pair in pairs: try: key, value = pair.split('=', maxsplit=1) d[url_decoder(key)] = url_decoder(value) except ValueError: raise ValueError('Wrong format of query') return d def url_decoder(url_line: str): url_line = url_line.replace('+', ' ') encoded = b'' i = 0 while i < len(url_line): if url_line[i] == '%': hex_value = url_line[i + 1: i + 3] if hex_value in _URI_RESERVED: integer = ord(_URI_RESERVED[hex_value]) else: integer = int(hex_value, 16) encoded += bytes([integer]) i += 3 continue else: encoded += bytes([ord(url_line[i])]) i += 1 return encoded.decode()