import logging from abc import ABC, abstractmethod from typing import Dict, Tuple from urllib.parse import urlparse from client.httpclient import FORMAT, HTTPClient from httplib import parser from httplib.exceptions import InvalidResponse, InvalidStatusLine, UnsupportedEncoding from httplib.message import Message from httplib.retriever import PreambleRetriever def create(method: str, message: Message): if method == "GET": return GetCommand(url, port) elif method == "HEAD": return HeadCommand(url, port) elif method == "POST": return PostCommand(url, port) elif method == "PUT": return PutCommand(url, port) else: raise ValueError() class AbstractCommand(ABC): path: str headers: Dict[str, str] def __init(self): pass @property @abstractmethod def command(self): pass class AbstractWithBodyCommand(AbstractCommand, ABC): def _build_message(self, message: str) -> bytes: body = input(f"Enter {self.command} data: ").encode(FORMAT) print() message += "Content-Type: text/plain\r\n" message += f"Content-Length: {len(body)}\r\n" message += "\r\n" message = message.encode(FORMAT) message += body message += b"\r\n" return message class HeadCommand(AbstractCommand): @property def command(self): return "HEAD" class GetCommand(AbstractCommand): def __init__(self, uri: str, port, dir=None): super().__init__(uri, port) self.dir = dir self.filename = None @property def command(self): return "GET" def _get_preamble(self, retriever): lines = retriever.retrieve() (version, status, msg) = parser.parse_status_line(next(lines)) headers = parser.parse_headers(lines) logging.debug("---response begin---\r\n%s--- response end---", "".join(retriever.buffer)) return Message(version, status, msg, headers) def _await_response(self, client, retriever): msg = self._get_preamble(retriever) from client import response_handler self.filename = response_handler.handle(client, msg, self, self.dir) class PostCommand(AbstractWithBodyCommand): @property def command(self): return "POST" class PutCommand(AbstractWithBodyCommand): @property def command(self): return "PUT"