Improve logging, fix small issues

This commit is contained in:
2021-03-28 15:58:07 +02:00
parent cd053bc74e
commit 210c03b73f
10 changed files with 58 additions and 60 deletions

View File

@@ -26,9 +26,9 @@ def main():
try: try:
main() main()
except UnhandledHTTPCode as e: except UnhandledHTTPCode as e:
print(f"[{e.status_code}] {e.cause}:\r\n{e.headers}") logging.info(f"[{e.status_code}] {e.cause}:\r\n{e.headers}")
sys.exit(2) sys.exit(2)
except Exception as e: except Exception as e:
print("[ABRT] Internal error: " + str(e), file=sys.stderr) logging.info("[ABRT] Internal error: %s", e)
logging.debug("Internal error", exc_info=e) logging.debug("Internal error", exc_info=e)
sys.exit(1) sys.exit(1)

View File

@@ -125,17 +125,34 @@ class AbstractCommand(ABC):
if not sub_request: if not sub_request:
client.close() client.close()
def _get_preamble(self, client):
"""
Returns the preamble (start-line and headers) of the response of this command.
@param client: the client object to retrieve from
@return: A Message object containing the HTTP-version, status code, status message, headers and buffer
"""
retriever = PreambleRetriever(client)
lines = retriever.retrieve()
(version, status, msg) = parser.parse_status_line(next(lines))
headers = parser.parse_headers(lines)
buffer = retriever.buffer
logging.debug("---response begin---\r\n%s---response end---", "".join(buffer))
return Message(version, status, msg, headers, buffer)
def _await_response(self, client): def _await_response(self, client):
""" """
Simple response method. Simple response method.
Receives the response and prints to stdout. Receives the response and prints to stdout.
""" """
while True:
line = client.read_line() msg = self._get_preamble(client)
print(line, end="")
if line in ("\r\n", "\n", ""): print("".join(msg.raw))
break
def _build_message(self, message: str) -> bytes: def _build_message(self, message: str) -> bytes:
return (message + "\r\n").encode(FORMAT) return (message + "\r\n").encode(FORMAT)
@@ -163,25 +180,6 @@ class AbstractCommand(ABC):
return host, path return host, path
class AbstractWithBodyCommand(AbstractCommand, ABC):
"""
The building block for creating an HTTP message for an HTTP method with a body (POST and PUT).
"""
def _build_message(self, message: str) -> bytes:
body = input(f"Enter {self.method} 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): class HeadCommand(AbstractCommand):
""" """
A Command for sending a `HEAD` request. A Command for sending a `HEAD` request.
@@ -207,22 +205,6 @@ class GetCommand(AbstractCommand):
def method(self): def method(self):
return "GET" return "GET"
def _get_preamble(self, client):
"""
Returns the preamble (start-line and headers) of the response of this command.
@param client: the client object to retrieve from
@return: A Message object containing the HTTP-version, status code, status message, headers and buffer
"""
retriever = PreambleRetriever(client)
lines = retriever.retrieve()
(version, status, msg) = parser.parse_status_line(next(lines))
headers = parser.parse_headers(lines)
buffer = retriever.buffer
logging.debug("---response begin---\r\n%s---response end---", "".join(buffer))
return Message(version, status, msg, headers, buffer)
def _await_response(self, client): def _await_response(self, client):
""" """
Handles the response of this command. Handles the response of this command.
@@ -233,6 +215,27 @@ class GetCommand(AbstractCommand):
self.filename = responsehandler.handle(client, msg, self, self.dir) self.filename = responsehandler.handle(client, msg, self, self.dir)
class AbstractWithBodyCommand(AbstractCommand, ABC):
"""
The building block for creating an HTTP message for an HTTP method with a body (POST and PUT).
"""
def _build_message(self, message: str) -> bytes:
input_line = input(f"Enter {self.method} data: ")
input_line += "\r\n"
body = input_line.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 PostCommand(AbstractWithBodyCommand): class PostCommand(AbstractWithBodyCommand):
""" """
A command for sending a `POST` request. A command for sending a `POST` request.

View File

@@ -1,6 +0,0 @@
from bs4 import BeautifulSoup
class HTMLParser:
def __init__(self, soup: BeautifulSoup):
pass

View File

@@ -65,7 +65,7 @@ class ResponseHandler(ABC):
class BasicResponseHandler(ResponseHandler): class BasicResponseHandler(ResponseHandler):
""" """
Response handler which skips the body of the message and only shows the headers. Response handler which will handle redirects and other HTTP status codes.
In case of a redirect, it will process it and pass it to the appropriate response handler. In case of a redirect, it will process it and pass it to the appropriate response handler.
""" """

View File

@@ -66,12 +66,10 @@ class HTTPServerException(HTTPException):
""" """
status_code: str status_code: str
message: str message: str
body: str
arg: str arg: str
def __init__(self, arg, body=""): def __init__(self, arg):
self.arg = arg self.arg = arg
self.body = body
class HTTPServerCloseException(HTTPServerException): class HTTPServerCloseException(HTTPServerException):
@@ -160,5 +158,6 @@ class InvalidRequestLine(BadRequest):
Request start-line is invalid Request start-line is invalid
""" """
def __init__(self, line): def __init__(self, line, arg):
super().__init__(arg)
self.request_line = line self.request_line = line

View File

@@ -72,7 +72,7 @@ def parse_request_line(line: str):
split = list(filter(None, line.rstrip().split(" ", 2))) split = list(filter(None, line.rstrip().split(" ", 2)))
if len(split) < 3: if len(split) < 3:
raise InvalidRequestLine(line) raise InvalidRequestLine(line, "missing argument in request-line")
method, target, version = split method, target, version = split
if method not in ("CONNECT", "DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT", "TRACE"): if method not in ("CONNECT", "DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT", "TRACE"):

View File

@@ -1 +0,0 @@
lxml~=4.6.2

View File

@@ -5,7 +5,7 @@ from abc import ABC, abstractmethod
from datetime import datetime from datetime import datetime
from httplib import parser from httplib import parser
from httplib.exceptions import NotFound, Forbidden, NotModified from httplib.exceptions import NotFound, Forbidden, NotModified, BadRequest
from httplib.httpsocket import FORMAT from httplib.httpsocket import FORMAT
from httplib.message import RequestMessage as Message from httplib.message import RequestMessage as Message
@@ -66,8 +66,6 @@ class AbstractCommand(ABC):
def _build_message(self, status: int, content_type: str, body: bytes, extra_headers=None): def _build_message(self, status: int, content_type: str, body: bytes, extra_headers=None):
if extra_headers is None:
extra_headers = {}
self._process_conditional_headers() self._process_conditional_headers()
message = f"HTTP/1.1 {status} {status_message[status]}\r\n" message = f"HTTP/1.1 {status} {status_message[status]}\r\n"
@@ -237,3 +235,9 @@ class PutCommand(AbstractModifyCommand):
@property @property
def _file_mode(self): def _file_mode(self):
return "w" return "w"
def execute(self):
if "content-range" in self.msg.headers:
raise BadRequest("PUT request contains Content-Range header")
super().execute()

View File

@@ -1,6 +1,4 @@
import logging import logging
import os
import sys
from socket import socket from socket import socket
from typing import Union from typing import Union
from urllib.parse import ParseResultBytes, ParseResult from urllib.parse import ParseResultBytes, ParseResult

View File

@@ -85,6 +85,7 @@ class Worker:
RequestHandler.send_error(conn, InternalServerError.status_code, InternalServerError.message) RequestHandler.send_error(conn, InternalServerError.status_code, InternalServerError.message)
break break
logging.info("Closing socket for client %s", addr)
conn.shutdown(socket.SHUT_RDWR) conn.shutdown(socket.SHUT_RDWR)
conn.close() conn.close()
# Finished, put back into queue # Finished, put back into queue