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 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user