def serve_file(sock: socket.socket, path: str, root: str = "www") -> None: """Given a socket and the relative path to a file (relative to SERVER_SOCK), send that file to the socket if it exists. If the file doesn't exist, send a "404 Not Found" response. """ root_path = os.path.abspath(root) if path == "/": path = "/index.html" abspath = os.path.normpath(os.path.join(root_path, path.lstrip("/"))) if not abspath.startswith(root_path): Response.from_status_code(404).send(sock) return try: with open(abspath, "rb") as f: content_type, encoding = mimetypes.guess_type(abspath) if content_type is None: content_type = "application/octet-stream" if encoding is not None: content_type += f"; charset={encoding}" res = Response(status="200 OK", body=f) res.headers.add("content-type", content_type) res.send(sock) return except FileNotFoundError: Response.from_status_code(404).send(sock) return
def handle_client(self, client_sock: socket.socket, client_addr: typing.Tuple[str, int]) -> None: print(f"New connection from {client_addr}...") with client_sock: try: req = Request.from_socket(client_sock) if "100-continue" in req.headers.get("expect", ""): Response.from_status_code(100).send(client_sock) try: content_len = int(req.headers.get("content-length", "0")) except ValueError: content_len = 0 if content_len: body = req.body.read(content_len) print("Request body", body) if req.method != 'GET': Response.from_status_code(405).send(client_sock) return serve_file(client_sock, req.path) except Exception as e: print(f"Failed to parse request: {e}") Response.from_status_code(404).send(client_sock)