import logging from logging import Logger from socket import socket from typing import Union from urllib.parse import ParseResultBytes, ParseResult from httplib import parser from httplib.exceptions import MethodNotAllowed, BadRequest from httplib.httpsocket import HTTPSocket from httplib.retriever import Retriever METHODS = ("GET", "HEAD", "PUT", "POST") class RequestHandler: conn: HTTPSocket logger: Logger def __init__(self, conn: socket, logger, host): self.conn = HTTPSocket(conn, host) self.logger = logger def listen(self): self.logger.debug("Parsing request line") logging.debug("test logger") (method, target, version) = parser.parse_request_line(self.conn) headers = parser.parse_request_headers(self.conn) self._validate_request(method, target, version, headers) self.logger.debug("Parsed request-line: version: %s, target: %r", method, target) headers = parser.get_headers(self.conn) self.logger.debug("Parsed headers: %r", headers) retriever = Retriever.create(self.conn, headers) body = retriever.retrieve() self.logger.debug("body: %r", body) def _check_request_line(self, method: str, target: Union[ParseResultBytes, ParseResult], version): if method not in METHODS: raise MethodNotAllowed(METHODS) # only origin-form and absolute-form are allowed if len(target.path) < 1 or target.path[0] != "/" or \ target.netloc not in ("http", "https") and target.hostname == "": raise BadRequest() if version not in ("1.0", "1.1"): raise BadRequest() def _validate_request(self, method, target, version, headers): self._check_request_line(method, target, version) if version == "1.1" and "host" not in headers: raise BadRequest()