From 7aac81520a05932c17f2918b2acf2794a9ef4179 Mon Sep 17 00:00:00 2001 From: pablusha Date: Thu, 31 Jul 2025 17:01:42 +0000 Subject: [PATCH] added pooop123124555 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit не --- main.py | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 main.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..876bc8f --- /dev/null +++ b/main.py @@ -0,0 +1,150 @@ +from urllib.parse import unquote + +import mimetypes +import datetime +import aiofiles +import asyncio +import time +import os +import re + +class WebServer: + def __init__(self): + self._addr = os.environ.get("ADDR", "localhost") + self._port = int(os.environ.get("PORT", 7856)) + + self._log_file = os.environ.get("FILE") + self.preset_file = os.environ.get("PRESET_FILE") + self.directory = os.environ.get("DIR") + + self._read_buffer = int(os.environ.get("READ_BUFFER", 16384)) + self._write_size = int(os.environ.get("WRITE_BUFFER", 16384)) + + self.conn_msg = os.environ.get("CONN_MSG", "conn from ") + self.start_msg = os.environ.get("START_MSG", "started at ") + self.get_msg = os.environ.get("GET_MSG", " got ") + self.e404_msg = os.environ.get("404_MSG", " err 404 ") + + + async def log(self, text: str, addr: tuple=None, file: str=None) -> None: + text = text.replace("", f"{addr[0]}:{addr[1]}" if addr else "") + text = text.replace("", file if file else "") + + if self._log_file: + async with aiofiles.open(self._log_file, mode="a") as file: + await file.write(text + "\n") + else: + print(text) + + + async def handle(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter) -> None: + addr = writer.get_extra_info("peername") + await self.log(self.conn_msg, addr) + data = await reader.read(self._read_buffer) + data = unquote(data.decode()) + if not data: return + + request = data.split("\n")[0] + file_name = request.split()[1][1:] + file_path = self.directory + file_name + + if os.path.isfile(file_path): + mime, _ = mimetypes.guess_type(file_path) + file_size = os.path.getsize(file_path) + if not mime: mime = "application/octet-stream" + if mime.startswith("text"): mime += "; charset=utf-8" + + headers = ( + "HTTP/1.1 200 OK\r\n", + f"Content-Type: {mime}\r\n", + f"Content-Length: {file_size}\r\n", + "\r\n" + ) + + writer.write("".join(headers).encode()) + await writer.drain() + + sent = 0 + async with aiofiles.open(file_path, "rb") as f: + while sent < file_size: + chunk = await f.read(self._write_size) + if not chunk: break + + writer.write(chunk) + await writer.drain() + + sent += len(chunk) + + + elif os.path.isdir(file_path): + resp = "" + async with aiofiles.open(self.preset_file, "r") as f: + resp = await f.read() + + files = "" + for file_name in sorted(os.listdir(file_path)): # TODO: добавить настройки отображения файла + file = "/".join(file_path.split("/")[1:]) +"/" + file_name + + if os.path.isdir(file_path + "/" + file_name): + file_name = "/" + file_name + + modify_time = (os.path.getmtime(file_path + "/" + file_name)) + modify_datetime = datetime.datetime.fromtimestamp(modify_time) + formatted_time = modify_datetime.strftime("%d.%m.%Y %H:%M:%S") + + files += f'{file_name} | {formatted_time}
' + + resp = resp.replace("FILES", files) + resp = resp.replace("//", "/") + resp = resp.encode() + headers = ( + "HTTP/1.1 200 OK\r\n" + f"Content-Type: text/html; charset=utf-8\r\n" + f"Content-Length: {len(resp)}\r\n" + "\r\n" + ) + + writer.write("".join(headers).encode() + resp) + else: + await self.log(self.e404_msg, addr, file_path) + response = ( # TODO: добавить страничку для 404 + "HTTP/1.1 404 Not Found\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "\r\n" + "

плоке плоке, 404

" + ) + writer.write(response.encode()) + await writer.drain() + return + + await self.log(self.get_msg, addr, file_path) + await writer.drain() + + + async def start(self) -> None: + server = await asyncio.start_server( + self.handle, + self._addr, + self._port + ) + await self.log(f"{self.start_msg}", (self._addr, self._port)) + + async with server: + await server.serve_forever() + + +async def main(): + s = WebServer() + if not s.directory: + print("directory not set!") + exit(1) + if not s.preset_file: + print("preset file not set!") + exit(1) + if not os.path.isfile(s.preset_file): + print("invalid preset file") + exit(1) + await s.start() + + +asyncio.run(main()) \ No newline at end of file