Initial deployable Flask application
This commit is contained in:
+101
@@ -0,0 +1,101 @@
|
||||
"""
|
||||
DrHider — Managed Flask приложение на платформе Штурвал.
|
||||
|
||||
Приложение создаётся фабрикой create_app().
|
||||
Штурвал запускает Flask самостоятельно (без Dockerfile/gunicorn).
|
||||
|
||||
Роуты разнесены по blueprint'ам:
|
||||
- main_bp: GET / — веб-интерфейс
|
||||
- health_bp: GET /health — проверка живости
|
||||
- api_bp: POST /api/drhider — обфускация документов
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
from flask import Flask
|
||||
|
||||
# Добавляем корень проекта в sys.path для импорта пакета drhider
|
||||
_sys_path_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
if _sys_path_root not in sys.path:
|
||||
sys.path.insert(0, _sys_path_root)
|
||||
|
||||
# Версия приложения (меняется при изменениях)
|
||||
VERSION = "0.0.79"
|
||||
|
||||
|
||||
def setup_logging():
|
||||
"""Настроить логирование. Уровень из env LOG_LEVEL (DEBUG/INFO/WARNING).
|
||||
|
||||
Логи пишутся в stderr (для локального запуска) И в файл /tmp/drhider.log
|
||||
(для кубера, где stdout/stderr контейнера может не попадать в kubectl logs).
|
||||
Путь файла можно переопределить env LOG_FILE.
|
||||
"""
|
||||
level_name = os.environ.get("LOG_LEVEL", "INFO").upper()
|
||||
level = getattr(logging, level_name, logging.INFO)
|
||||
log_file = os.environ.get("LOG_FILE", "/tmp/drhider.log")
|
||||
fmt = logging.Formatter("%(asctime)s %(levelname)s [%(name)s] %(message)s", "%Y-%m-%d %H:%M:%S")
|
||||
root = logging.getLogger()
|
||||
root.setLevel(level)
|
||||
root.handlers.clear()
|
||||
sh = logging.StreamHandler(sys.stderr)
|
||||
sh.setLevel(level)
|
||||
sh.setFormatter(fmt)
|
||||
root.addHandler(sh)
|
||||
try:
|
||||
fh = logging.FileHandler(log_file, encoding="utf-8")
|
||||
fh.setLevel(level)
|
||||
fh.setFormatter(fmt)
|
||||
root.addHandler(fh)
|
||||
except Exception as e: # файл не открылся — не падаем
|
||||
sys.stderr.write(f"[app] cannot open log file {log_file}: {e}\n")
|
||||
for name in ("drhider", "app", "routes", "session", __name__):
|
||||
logging.getLogger(name).setLevel(level)
|
||||
log = logging.getLogger("app")
|
||||
log.info("Logging configured, level=%s, version=%s, file=%s", level_name, VERSION, log_file)
|
||||
|
||||
|
||||
def create_app():
|
||||
"""Создать и настроить Flask-приложение.
|
||||
|
||||
Штурвал запускает из директории site/:
|
||||
from app import app
|
||||
|
||||
Поэтому routes/ доступен как обычный подпакет.
|
||||
|
||||
Returns:
|
||||
Экземпляр Flask с зарегистрированными blueprint'ами.
|
||||
"""
|
||||
setup_logging()
|
||||
app = Flask(__name__)
|
||||
|
||||
# Конфигурация
|
||||
app.config["VERSION"] = VERSION
|
||||
app.config["MAX_CONTENT_LENGTH"] = 50 * 1024 * 1024 # 50 MB (лимит на один файл)
|
||||
|
||||
# Регистрируем blueprint'ы
|
||||
from routes import register_routes
|
||||
|
||||
register_routes(app)
|
||||
|
||||
# Запрещаем кэширование — F5 всегда грузит свежую страницу
|
||||
@app.after_request
|
||||
def no_cache(response):
|
||||
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
|
||||
response.headers["Pragma"] = "no-cache"
|
||||
response.headers["Expires"] = "0"
|
||||
return response
|
||||
|
||||
return app
|
||||
|
||||
|
||||
# Экземпляр приложения — точка входа для Штурвала
|
||||
app = create_app()
|
||||
|
||||
# Штурвал запускает: cd site && python app.py
|
||||
if __name__ == "__main__":
|
||||
from waitress import serve
|
||||
serve(app, host="0.0.0.0", port=5000, threads=8)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user