Files
omni-parse/tools/_port_serve.py

85 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""serve.py: валидация int-параметров, eviction JOBS, токен на POST, лимит тела."""
from pathlib import Path
p = Path(r"C:/Users/User/tmp/omni-parse/omni/serve.py")
s = p.read_text(encoding="utf-8")
rep = []
if "\nimport os\n" not in s:
s = s.replace("import json\n", "import json\nimport os\n", 1)
rep.append("+ import os")
helper = '''
UI_TOKEN = os.environ.get("OMNI_UI_TOKEN", "")
def _ui_auth(req):
"""Панель наружу: без токена мутации открыты любому, кто дошёл до порта."""
if not UI_TOKEN:
return True
return req.headers.get("X-Omni-Token") == UI_TOKEN
def _intv(q, key, default, lo, hi):
"""int из query без падений: ?limit=abc раньше давал трейс и обрыв соединения,
?limit=-1 отдавал всю базу (SQLite LIMIT -1 = без лимита)."""
try:
v = int((q.get(key) or [str(default)])[0])
except (TypeError, ValueError):
return default
return max(lo, min(hi, v))
'''
assert "def _job(jid, **kw):" in s
s = s.replace("def _job(jid, **kw):", helper.strip("\n") + "\n\n\ndef _job(jid, **kw):", 1)
s = s.replace(''' with _LOCK:
cur = JOBS.get(jid) or {}
cur.update(kw)
JOBS[jid] = cur''',
''' with _LOCK:
cur = JOBS.get(jid) or {}
cur.update(kw)
cur["_ts"] = time.time()
JOBS[jid] = cur
if len(JOBS) > 400: # раньше росло без границ (500 запусков -> 500 записей)
dead = sorted(JOBS.items(), key=lambda kv: kv[1].get("_ts", 0))[:len(JOBS) - 300]
for k, _v in dead:
JOBS.pop(k, None)''')
rep.append("JOBS eviction")
pairs = [
('limit = max(1, min(500, int((q.get("limit") or ["80"])[0])))', 'limit = _intv(q, "limit", 80, 1, 500)'),
('lim = max(1, min(200, int((q.get("limit") or ["40"])[0])))', 'lim = _intv(q, "limit", 40, 1, 200)'),
('lim = max(1, min(40, int((q.get("limit") or ["14"])[0])))', 'lim = _intv(q, "limit", 14, 1, 40)'),
('limit = min(int((q.get("limit") or ["40"])[0]), 200)', 'limit = _intv(q, "limit", 40, 1, 200)'),
('offset = int((q.get("offset") or ["0"])[0])', 'offset = _intv(q, "offset", 0, 0, 1_000_000)'),
('hosts = max(5, min(120, int((q.get("hosts") or ["40"])[0])))', 'hosts = _intv(q, "hosts", 40, 5, 120)'),
('add = max(1, min(60, int((q.get("add") or ["25"])[0])))', 'add = _intv(q, "add", 25, 1, 60)'),
]
for old, new in pairs:
if old in s:
s = s.replace(old, new)
rep.append("int -> " + new.split(" = ")[0] + " " + new.split("_intv")[1][:26])
old_post = ''' def do_POST(self):
u = urllib.parse.urlsplit(self.path)
n = int(self.headers.get("Content-Length") or 0)'''
new_post = ''' def do_POST(self):
u = urllib.parse.urlsplit(self.path)
if not _ui_auth(self):
return self._json({"error": "unauthorized"}, 401)
n = min(int(self.headers.get("Content-Length") or 0), 2_000_000)'''
assert old_post in s, "do_POST шаблон не найден"
s = s.replace(old_post, new_post)
rep.append("POST: токен + лимит тела")
s = s.replace(''' print(f"omni ui: http://127.0.0.1:{port} (источников {len(sources.all_sources())})")''',
''' print(f"omni ui: http://127.0.0.1:{port} (источников {len(sources.all_sources())})")
if not UI_TOKEN:
print("внимание: OMNI_UI_TOKEN не задан — POST /api/* без авторизации; наружу только за nginx с basic-auth")''')
p.write_text(s, encoding="utf-8", newline="\n")
print("\n".join(rep))
print("остались сырые int((q.get:", s.count("int((q.get"))