From 4ed6833a9eedcd8d075677dd3d95b542929df9c6 Mon Sep 17 00:00:00 2001 From: pablusha Date: Sat, 9 Aug 2025 20:00:09 +0300 Subject: [PATCH 1/6] da emae --- main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index cab8601..3132d44 100644 --- a/main.py +++ b/main.py @@ -144,10 +144,10 @@ class WebServer: else: - await self.log(self.e404_msg, addr, file_path) - file_size = os.path.getsize(file_path) + await self.log(config.err_msgs[404], addr, config.err_files[404]) + file_size = os.path.getsize(config.err_files[404]) await self.send_headers(writer, 404, file_size) - await self.send_file(writer, self._e404_file, file_size) + await self.send_file(writer, config.err_files[404], file_size) writer.close() await writer.wait_closed() From 055a3167e808fa1b1bf925ac5b1ff8b0c2b16a01 Mon Sep 17 00:00:00 2001 From: pablusha Date: Sat, 9 Aug 2025 20:32:27 +0300 Subject: [PATCH 2/6] fixed gzaza --- main.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/main.py b/main.py index 3132d44..8ce6c8b 100644 --- a/main.py +++ b/main.py @@ -15,8 +15,6 @@ STATUS = { 418: "418 I'm a teapot" } -# file_size = os.path.getsize(file_path) - class WebServer: async def log(self, text: str, addr: tuple=None, file: str=None) -> None: text = text.replace("", f"{addr[0]}:{addr[1]}" if addr else "") @@ -90,7 +88,7 @@ class WebServer: await self.send_headers(writer, 418, file_size) await self.send_file(writer, config.err_files[418], file_size) - await writer.close() + writer.close() await writer.wait_closed() return From 0984e169ebc39e7d8932a09cfdd862f94ef1b652 Mon Sep 17 00:00:00 2001 From: pablusha Date: Sun, 10 Aug 2025 20:45:45 +0300 Subject: [PATCH 3/6] ebat obnova --- README.md | 65 +++++++++++++++++++++++++++++++++++++++++-------------- config.py | 6 ++++- main.py | 37 ++++++++++++++++++++++--------- utils.py | 13 +++++++++++ 4 files changed, 94 insertions(+), 27 deletions(-) create mode 100644 utils.py diff --git a/README.md b/README.md index 6e049ef..492abce 100644 --- a/README.md +++ b/README.md @@ -1,48 +1,81 @@ -## debweb +# debweb **debweb** - простой webserver для дебилов (for me) на асинхронных сокетах -## установка и настройка +# установка и настройка debweb использует всего одну стороннюю библиотеку - aiofiles. ее можно установить с помощью ```bash pip install aiofiles ``` -> [!IMPORTANT] + конфигурация сия шедевра происходит в файле `config.py` -### основное +## основное - `name` - название сервера, отображается в http заголовках +- `proxied` - указывает, находится ли сервер за прокси -### сеть +## сеть - `addr` - адрес сервера - `port` - порт сервера -### файлы и директории +## файлы и директории - `log_file` - файл логов (по умолчанию вывод в консоль) -- `preset_file` - файл пресета. обычный html документ. но в нем нужно указать одиночный тег `` для отображения файлов в директории -- `directory` - рабочая директория **обязательно с / на конце!!!!** +- `preset_file` - файл пресета +- `directory` - рабочая директория -### буферы +## буферы -- `read_buffer` - буфер для запроса +- `read_buffer` - размер буфера для запросов - `write_buffer` - размер буфера при отправке файлов -### логи +## логи - `start_msg` - лог при старте сервера - `conn_msg` - лог при подключении - `get_msg` - лог при GET запросе -`` будет заменен на адрес клиента +## теги -`` будет заменен на файл / директорию, к которой запрашивается доступ +- `` - адрес клиента +- `` - файл / директория, к которой запрашивается доступ -### ошибки +## шаблоны -- `e404_file` - html файл, который будет отправлен при ошибке 404 -- `e404_msg` - лог при ошибке 404 \ No newline at end of file +- `file_entry` - шаблон для генерации строк файлов в листинге директории +- `dir_entry` - шаблон для генерации строк каталогов в листинге директории +- `time_format` - формат времени для всего документа + +### теги шаблонов + +- `` - название элемента +- `` - относительный путь элемента +- `` - дата создания элемент +- `` - дата модификации элемента +- `` - размер файла в байтах +- `` - размер файла в килобайтах +- `` - размер файла в мегабайтах +- все остальные html теги + +## preset.html + +обычный html документ, являющийся шаблоном для листинга каталога + +### теги пресета + +- `` - отображает все элементы директории +- `` - количество файлов +- `` - количество подкаталогов +- `` - общее количество элементов +- `` - название сервера +- `` - время обработки страницы +- `` - время на сервере + +## ошибки + +- `err_Files` - словарь с кодами ошибок и файлами, которые отправляются при этих ошибках +- `err_msgs` - словарь с кодами ошибок и логами, которые отправляются при этих ошибках \ No newline at end of file diff --git a/config.py b/config.py index 0379ec4..ac4496d 100644 --- a/config.py +++ b/config.py @@ -1,4 +1,4 @@ -name="debweb 1.1.3" +name="debweb 1.2.0" proxied=False addr="localhost" @@ -15,6 +15,10 @@ start_msg="started at " conn_msg="conn from " get_msg=" got " +file_entry = "
\n" +dir_entry = "
\n" +time_format = "%a %b %e %H:%M:%S %Z %Y" + err_files = { 404: "html/404.html", 403: "html/403.html", diff --git a/main.py b/main.py index 8ce6c8b..69e1bbe 100644 --- a/main.py +++ b/main.py @@ -5,6 +5,8 @@ import datetime import aiofiles import asyncio import config +import utils +import time import os STATUS = { @@ -60,9 +62,10 @@ class WebServer: async def handle(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter) -> None: addr = writer.get_extra_info("peername") await self.log(config.conn_msg, addr) + conn_time = time.time() + rdata = await reader.read(config.read_buffer) data = rdata.decode() - if not data: return real_addr = None @@ -110,9 +113,10 @@ class WebServer: files = "" base_path = os.path.relpath(file_path, config.directory).replace('\\', '/') - if base_path == '.': - base_path = '' + if base_path == '.': base_path = '' + file_count = 0 + dir_count = 0 for item in sorted(os.listdir(file_path)): item_path = os.path.join(file_path, item) is_dir = os.path.isdir(item_path) @@ -123,16 +127,29 @@ class WebServer: if is_dir: rel_path += "/" item += "/" - - modify_time = os.path.getmtime(item_path) - modify_datetime = datetime.datetime.fromtimestamp(modify_time) - formatted_time = modify_datetime.strftime("%d.%m.%Y %H:%M:%S") - + dir_count += 1 + else: file_count += 1 + rel_path_encoded = rel_path.replace(' ', '%20').replace('#', '%23') - - files += f'{item} | {formatted_time}
\n' + + entry = config.dir_entry if is_dir else config.file_entry + entry = entry.replace("", item) + entry = entry.replace("", rel_path_encoded) + entry = entry.replace("", utils.get_create_time(item_path, config.time_format)) + entry = entry.replace("", utils.get_mod_time(item_path, config.time_format)) + entry = entry.replace("", f"{os.path.getsize(item_path)}B") + entry = entry.replace("", f"{format(os.path.getsize(item_path) / 1024, ".2f")}KB") + entry = entry.replace("", f"{format(os.path.getsize(item_path) / 1024 ** 2, ".2f")}MB") + + files += entry resp = resp.replace("", files) + resp = resp.replace("", str(file_count)) + resp = resp.replace("", str(dir_count)) + resp = resp.replace("", str(file_count + dir_count)) + resp = resp.replace("", config.name) + resp = resp.replace("", format(time.time() - conn_time, ".3f")) + resp = resp.replace("", datetime.datetime.now().strftime(config.time_format)) resp = resp.encode() await self.send_headers(writer, 200, len(resp)) diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..ba6b0bf --- /dev/null +++ b/utils.py @@ -0,0 +1,13 @@ +import datetime +import os + +def get_mod_time(path: str, format: str="%a %b %e %H:%M:%S %Z %Y") -> str: + modify_time = os.path.getmtime(path) + modify_datetime = datetime.datetime.fromtimestamp(modify_time) + return modify_datetime.strftime(format) + + +def get_create_time(path: str, format: str="%a %b %e %H:%M:%S %Z %Y") -> str: + create_time = os.path.getctime(path) + create_datetime = datetime.datetime.fromtimestamp(create_time) + return create_datetime.strftime(format) \ No newline at end of file From 1d0ef1535f735517073996ce74fe357c8077ee9c Mon Sep 17 00:00:00 2001 From: pablusha Date: Mon, 11 Aug 2025 13:58:54 +0300 Subject: [PATCH 4/6] cool patch with 5 lines of code --- README.md | 2 +- main.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 492abce..7288ce8 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ pip install aiofiles ## preset.html -обычный html документ, являющийся шаблоном для листинга каталога +обычный html документ, являющийся шаблоном для листинга каталога. если в директории будет находиться preset.html, сервер будет использовать именно его. в противном случае - тот, который указан в конфиге. ### теги пресета diff --git a/main.py b/main.py index 69e1bbe..1537b58 100644 --- a/main.py +++ b/main.py @@ -108,7 +108,11 @@ class WebServer: elif os.path.isdir(file_path): resp = "" - async with aiofiles.open(config.preset_file, "r", encoding="utf-8") as f: + if os.path.isfile(os.path.join(file_path, "preset.html")): + preset_file = os.path.join(file_path, "preset.html") + else: + preset_file = config.preset_file + async with aiofiles.open(preset_file, "r", encoding="utf-8") as f: resp = await f.read() files = "" From 8c07d87efa4bd4f615fb66b51f601c65d5f81900 Mon Sep 17 00:00:00 2001 From: pablusha Date: Wed, 13 Aug 2025 00:38:56 +0300 Subject: [PATCH 5/6] =?UTF-8?q?=D0=BA=D0=B0=D0=BA=D0=B0=D1=88=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.py | 2 +- main.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config.py b/config.py index ac4496d..f10c2a1 100644 --- a/config.py +++ b/config.py @@ -1,4 +1,4 @@ -name="debweb 1.2.0" +name="debweb 1.2.2" proxied=False addr="localhost" diff --git a/main.py b/main.py index 1537b58..7397789 100644 --- a/main.py +++ b/main.py @@ -21,6 +21,7 @@ class WebServer: 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 "") + text = text.replace("