From ebe5c6ec902315212617b730eb4738166423fb1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=AD=D0=BB=D1=8C=D0=BD=D0=B0=D1=80?= Date: Tue, 10 Mar 2026 20:38:53 +0400 Subject: [PATCH] Refactor: fix socket leak, deduplicate stat/path logic, simplify config - get_local_ip: use context manager to prevent socket leak - _route_files: single stat() per file instead of two - _safe_path helper: DRY path resolution for download/delete - load_config: loop over vars(args) instead of 6 repetitive blocks - Remove stale comment from index.html Co-Authored-By: Claude Opus 4.6 --- share.py | 42 +++++++++++++++++------------------------- static/index.html | 2 -- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/share.py b/share.py index 7f26fbc..4f2a537 100755 --- a/share.py +++ b/share.py @@ -39,11 +39,9 @@ def cleanup_loop(upload_dir: Path, max_age: int): def get_local_ip(): try: - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.connect(("8.8.8.8", 80)) - ip = s.getsockname()[0] - s.close() - return ip + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: + s.connect(("8.8.8.8", 80)) + return s.getsockname()[0] except Exception: return "127.0.0.1" @@ -158,15 +156,19 @@ class Handler(http.server.BaseHTTPRequestHandler): self._respond(self.server.html, "text/html; charset=utf-8") def _route_files(self): - files = [] - for p in sorted(self.server.upload_dir.iterdir(), key=lambda p: p.stat().st_mtime, reverse=True): + entries = [] + for p in self.server.upload_dir.iterdir(): if p.is_file(): - files.append({"name": p.name, "size": p.stat().st_size, "type": _file_type(p)}) - self._json(files) + entries.append((p, p.stat())) + entries.sort(key=lambda e: e[1].st_mtime, reverse=True) + self._json([{"name": p.name, "size": st.st_size, "type": _file_type(p)} for p, st in entries]) + + def _safe_path(self, prefix_len: int) -> Path: + name = urllib.parse.unquote(self.path[prefix_len:]) + return self.server.upload_dir / Path(name).name def _route_download(self): - name = urllib.parse.unquote(self.path[4:]) - safe = self.server.upload_dir / Path(name).name + safe = self._safe_path(4) if not safe.is_file(): self.send_error(404) return @@ -191,8 +193,7 @@ class Handler(http.server.BaseHTTPRequestHandler): self._json({"ok": True, "count": count}) def _route_delete(self): - name = urllib.parse.unquote(self.path[5:]) - safe = self.server.upload_dir / Path(name).name + safe = self._safe_path(5) if safe.is_file(): safe.unlink() self._json({"ok": True}) @@ -260,18 +261,9 @@ def load_config() -> dict: p.add_argument("--refresh", type=int) args = p.parse_args() - if args.port is not None: - conf["port"] = str(args.port) - if args.dir is not None: - conf["dir"] = args.dir - if args.ttl is not None: - conf["ttl"] = str(args.ttl) - if args.san is not None: - conf["san"] = " ".join(args.san) - if args.lang is not None: - conf["lang"] = args.lang - if args.refresh is not None: - conf["refresh"] = str(args.refresh) + for key, val in vars(args).items(): + if val is not None: + conf[key] = " ".join(val) if isinstance(val, list) else str(val) return conf diff --git a/static/index.html b/static/index.html index 3e9d462..996237b 100644 --- a/static/index.html +++ b/static/index.html @@ -259,8 +259,6 @@ $('lang-sw').addEventListener('click', e => { if (e.target.dataset.l) setLang(e.target.dataset.l); }); -/* File type is determined server-side via /files API ("text" | "image" | "other") */ - /* ── Helpers ── */ let toastTimer;