Disable all caching layers for instant content updates
This commit is contained in:
+20
-1
@@ -1,10 +1,12 @@
|
||||
import asyncio
|
||||
import hashlib
|
||||
import os
|
||||
from time import perf_counter
|
||||
|
||||
from fastapi import Depends, FastAPI, Request
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from starlette.middleware.cors import CORSMiddleware
|
||||
from starlette.responses import Response as StarletteResponse
|
||||
from starlette.staticfiles import StaticFiles
|
||||
|
||||
from audit import ensure_api_context, log_api_access, record_api_access_event_background
|
||||
@@ -40,12 +42,29 @@ app.add_middleware(
|
||||
|
||||
|
||||
@app.middleware("http")
|
||||
async def security_headers_middleware(request: Request, call_next):
|
||||
async def security_and_cache_middleware(request: Request, call_next):
|
||||
response = await call_next(request)
|
||||
response.headers.setdefault("X-Content-Type-Options", "nosniff")
|
||||
response.headers.setdefault("X-Frame-Options", "DENY")
|
||||
response.headers.setdefault("Referrer-Policy", "strict-origin-when-cross-origin")
|
||||
response.headers.setdefault("X-XSS-Protection", "1; mode=block")
|
||||
|
||||
content_type = response.headers.get("content-type", "")
|
||||
if request.method == "GET" and response.status_code == 200 and "application/json" in content_type:
|
||||
body = b""
|
||||
async for chunk in response.body_iterator:
|
||||
body += chunk
|
||||
etag = '"' + hashlib.md5(body).hexdigest() + '"'
|
||||
if_none_match = request.headers.get("if-none-match", "")
|
||||
client_etags = [t.strip() for t in if_none_match.split(",") if t.strip()]
|
||||
if etag in client_etags or if_none_match.strip() == "*":
|
||||
return StarletteResponse(status_code=304, headers={"ETag": etag, "Cache-Control": "no-cache"})
|
||||
headers = dict(response.headers)
|
||||
headers["ETag"] = etag
|
||||
headers["Cache-Control"] = "no-cache"
|
||||
return StarletteResponse(content=body, status_code=200, headers=headers, media_type=response.media_type)
|
||||
|
||||
response.headers.setdefault("Cache-Control", "no-store")
|
||||
return response
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ def build_settings_web_kb() -> InlineKeyboardBuilder:
|
||||
|
||||
enabled = bool(WEB_CONFIG.get("WEB_ENABLED", False))
|
||||
url = str(WEB_CONFIG.get("SITE_URL") or "не указан")
|
||||
|
||||
builder.row(
|
||||
InlineKeyboardButton(
|
||||
text=f"{'✅' if enabled else '❌'} Сайт {'включён' if enabled else 'выключен'}",
|
||||
@@ -47,20 +46,22 @@ def build_settings_web_kb() -> InlineKeyboardBuilder:
|
||||
return builder
|
||||
|
||||
|
||||
@router.callback_query(AdminPanelCallback.filter(F.action == "settings_web"))
|
||||
async def open_web_settings(callback: CallbackQuery) -> None:
|
||||
def _web_settings_text() -> str:
|
||||
enabled = bool(WEB_CONFIG.get("WEB_ENABLED", False))
|
||||
url = str(WEB_CONFIG.get("SITE_URL") or "не указан")
|
||||
|
||||
text = (
|
||||
return (
|
||||
"<b>🌐 Настройки веб-сайта</b>\n\n"
|
||||
f"Статус: {'✅ Включён' if enabled else '❌ Выключен'}\n"
|
||||
f"URL: <code>{url}</code>\n\n"
|
||||
"Сайт может работать на отдельном домене и сервере.\n"
|
||||
"При выключении кнопка «Личный кабинет» скрывается из бота."
|
||||
)
|
||||
|
||||
|
||||
@router.callback_query(AdminPanelCallback.filter(F.action == "settings_web"))
|
||||
async def open_web_settings(callback: CallbackQuery) -> None:
|
||||
await callback.message.edit_text(
|
||||
text=text,
|
||||
text=_web_settings_text(),
|
||||
reply_markup=build_settings_web_kb().as_markup(),
|
||||
)
|
||||
await callback.answer()
|
||||
@@ -77,18 +78,8 @@ async def toggle_web_enabled(callback: CallbackQuery) -> None:
|
||||
|
||||
status = "✅ Сайт включён" if new_config["WEB_ENABLED"] else "❌ Сайт выключен"
|
||||
await callback.answer(status, show_alert=True)
|
||||
|
||||
enabled = new_config["WEB_ENABLED"]
|
||||
url = str(new_config.get("SITE_URL") or "не указан")
|
||||
text = (
|
||||
"<b>🌐 Настройки веб-сайта</b>\n\n"
|
||||
f"Статус: {'✅ Включён' if enabled else '❌ Выключен'}\n"
|
||||
f"URL: <code>{url}</code>\n\n"
|
||||
"Сайт может работать на отдельном домене и сервере.\n"
|
||||
"При выключении кнопка «Личный кабинет» скрывается из бота."
|
||||
)
|
||||
await callback.message.edit_text(
|
||||
text=text,
|
||||
text=_web_settings_text(),
|
||||
reply_markup=build_settings_web_kb().as_markup(),
|
||||
)
|
||||
|
||||
@@ -193,17 +184,7 @@ async def set_web_url(message: Message, state: FSMContext) -> None:
|
||||
await update_web_config(session, new_config)
|
||||
|
||||
await state.clear()
|
||||
|
||||
enabled = new_config.get("WEB_ENABLED", False)
|
||||
display_url = url or "не указан"
|
||||
text = (
|
||||
"<b>🌐 Настройки веб-сайта</b>\n\n"
|
||||
f"Статус: {'✅ Включён' if enabled else '❌ Выключен'}\n"
|
||||
f"URL: <code>{display_url}</code>\n\n"
|
||||
"Сайт может работать на отдельном домене и сервере.\n"
|
||||
"При выключении кнопка «Личный кабинет» скрывается из бота."
|
||||
)
|
||||
await message.answer(
|
||||
text=text,
|
||||
text=_web_settings_text(),
|
||||
reply_markup=build_settings_web_kb().as_markup(),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user