Merge branch 'BATON-SEC-007-backend_dev'
This commit is contained in:
commit
0a5ee35a4e
3 changed files with 13 additions and 15 deletions
|
|
@ -4,7 +4,6 @@ import asyncio
|
|||
import hashlib
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
from contextlib import asynccontextmanager
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
|
@ -113,7 +112,7 @@ app.add_middleware(
|
|||
@app.get("/health")
|
||||
@app.get("/api/health")
|
||||
async def health() -> dict[str, Any]:
|
||||
return {"status": "ok", "timestamp": int(time.time())}
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
@app.post("/api/register", response_model=RegisterResponse)
|
||||
|
|
@ -153,7 +152,7 @@ async def signal(body: SignalRequest, _: None = Depends(rate_limit_signal)) -> S
|
|||
f"⏰ {ts.strftime('%H:%M:%S')} UTC\n"
|
||||
f"{geo_info}"
|
||||
)
|
||||
await telegram.send_message(text)
|
||||
asyncio.create_task(telegram.send_message(text))
|
||||
|
||||
return SignalResponse(status="ok", signal_id=signal_id)
|
||||
|
||||
|
|
|
|||
|
|
@ -17,24 +17,23 @@ _TELEGRAM_API = "https://api.telegram.org/bot{token}/{method}"
|
|||
async def send_message(text: str) -> None:
|
||||
url = _TELEGRAM_API.format(token=config.BOT_TOKEN, method="sendMessage")
|
||||
async with httpx.AsyncClient(timeout=10) as client:
|
||||
while True:
|
||||
for attempt in range(3):
|
||||
resp = await client.post(url, json={"chat_id": config.CHAT_ID, "text": text})
|
||||
if resp.status_code == 429:
|
||||
retry_after = resp.json().get("parameters", {}).get("retry_after", 30)
|
||||
logger.warning("Telegram 429, sleeping %s sec", retry_after)
|
||||
await asyncio.sleep(retry_after)
|
||||
sleep = retry_after * (attempt + 1)
|
||||
logger.warning("Telegram 429, sleeping %s sec (attempt %d)", sleep, attempt + 1)
|
||||
await asyncio.sleep(sleep)
|
||||
continue
|
||||
if resp.status_code >= 500:
|
||||
logger.error("Telegram 5xx: %s", resp.text)
|
||||
await asyncio.sleep(30)
|
||||
resp2 = await client.post(
|
||||
url, json={"chat_id": config.CHAT_ID, "text": text}
|
||||
)
|
||||
if resp2.status_code != 200:
|
||||
logger.error("Telegram retry failed: %s", resp2.text)
|
||||
continue
|
||||
elif resp.status_code != 200:
|
||||
logger.error("Telegram error %s: %s", resp.status_code, resp.text)
|
||||
break
|
||||
else:
|
||||
logger.error("Telegram send_message: all 3 attempts failed, message dropped")
|
||||
|
||||
|
||||
async def set_webhook(url: str, secret: str) -> None:
|
||||
|
|
|
|||
|
|
@ -54,14 +54,14 @@ async def test_health_returns_status_ok():
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_health_returns_timestamp():
|
||||
"""GET /health должен вернуть поле timestamp в JSON."""
|
||||
async def test_health_no_timestamp():
|
||||
"""GET /health не должен возвращать поле timestamp (устраняет time-based fingerprinting)."""
|
||||
async with make_app_client() as client:
|
||||
response = await client.get("/health")
|
||||
|
||||
data = response.json()
|
||||
assert "timestamp" in data
|
||||
assert isinstance(data["timestamp"], int)
|
||||
assert "timestamp" not in data
|
||||
assert data == {"status": "ok"}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue