58 lines
1.8 KiB
Python
58 lines
1.8 KiB
Python
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()
|