diff --git a/admin.html b/admin.html
index a59e582..efdce47 100644
--- a/admin.html
+++ b/admin.html
@@ -752,7 +752,15 @@ function esc(s) {
async function api(path, opts) {
const res = await fetch(path, { ...opts, headers: { "Content-Type": "application/json", ...(opts && opts.headers) } });
if (res.status === 401) { showLogin(); throw new Error("unauthorized"); }
- if (!res.ok) throw new Error(await res.text());
+ if (!res.ok) {
+ const text = await res.text();
+ let message = text;
+ try {
+ const parsed = JSON.parse(text);
+ if (parsed && typeof parsed.detail === "string") message = parsed.detail;
+ } catch (e) {}
+ throw new Error(message);
+ }
const ct = res.headers.get("content-type") || "";
return ct.includes("application/json") ? res.json() : res.text();
}
diff --git a/api.py b/api.py
index a65ae0e..7a39d45 100644
--- a/api.py
+++ b/api.py
@@ -530,6 +530,8 @@ def admin_get_webhook_settings(request: Request):
def admin_set_webhook_settings(request: Request, body: dict = Body(...)):
require_admin(request)
url = (body.get("url") or "").strip()
+ if url and not (url.startswith("http://") or url.startswith("https://")):
+ raise HTTPException(400, "URL должен начинаться с http:// или https://")
_update_env_var("WEBHOOK_URL", url)
if url and not legal.read_env_var("WEBHOOK_SECRET", ""):
_update_env_var("WEBHOOK_SECRET", secrets.token_hex(24))