Spaces:
Running
Running
Download app/main.py from free-apis-collection/markitdown: direct link, hf CLI and curl.
- Browser
- Download file 5.85 kB
-
https://huggingface.co/spaces/free-apis-collection/markitdown/resolve/main/app/main.py
- Command line
-
hf download hf://spaces/free-apis-collection/markitdown/app/main.py
-
curl -L -o main.py https://huggingface.co/spaces/free-apis-collection/markitdown/resolve/main/app/main.py
5.85 kB
| """Application entrypoint β single monolithic FastAPI app. | |
| Routes are grouped by the deployed service they replace (executor, csv, | |
| db, chatbot, interpreter, embeddings). All request validation, error handling, | |
| CORS and auth wiring lives here. | |
| """ | |
| from __future__ import annotations | |
| import asyncio | |
| from contextlib import asynccontextmanager | |
| from fastapi import FastAPI, HTTPException, Request, status | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import JSONResponse | |
| from app.config import settings | |
| from app.core.banner import print_startup_banner | |
| from app.core.deps import ServiceAuth | |
| from app.core.exceptions import register_exception_handlers | |
| from app.core.logging import setup_logging, get_logger | |
| from app.core.pool import shutdown | |
| from app.core.redis import get_redis | |
| # from app.monitoring.manager import manager as ws_manager | |
| # from app.monitoring.metrics import get_snapshot, system_sampler | |
| # from app.monitoring.middleware import MonitoringMiddleware | |
| # from app.monitoring.router import router as monitoring_router | |
| from app.routers import chatbot, csv_service, db, embeddings, executor, files, interpreter, report_jobs, db_sync_jobs | |
| from app.services.db.mongo import close_mongo_clients | |
| from app.services.db.sql import close_db_pools | |
| from app.services.cron_scheduler import start_cron_scheduler | |
| setup_logging("DEBUG" if settings.debug else "INFO") | |
| logger = get_logger(__name__) | |
| # Extreme top: ASCII banner β details β huge horizontal line, then the app starts. | |
| print_startup_banner() | |
| async def _self_ping() -> None: | |
| """Background self-ping: keeps the HF Space warm via its https /ping URL. | |
| Sends Bearer <HF_TOKEN (fallback app auth token)>. /ping itself is | |
| public, so the header is ignored today β it only matters if /ping ever | |
| becomes protected. Runs every SELF_PING_INTERVAL seconds. | |
| """ | |
| if not settings.self_ping_enabled: | |
| logger.info("self-ping disabled (SELF_PING_ENABLED=false) β background task exiting") | |
| return | |
| url = settings.effective_self_ping_url | |
| if not url or not url.startswith("https://"): | |
| logger.warning("self-ping enabled but no https URL resolved (set SELF_PING_URL or SPACE_ID) β skipping") | |
| return | |
| interval = int(settings.self_ping_interval or 600) | |
| token = settings.effective_ping_token | |
| headers = {"Authorization": f"Bearer {token}"} if token else None | |
| logger.info("self-ping enabled: url=%s interval=%ss auth=%s", url, interval, "Bearer ***" if token else "none") | |
| import httpx | |
| while True: | |
| try: | |
| async with httpx.AsyncClient(timeout=30.0) as client: | |
| resp = await client.get(url, headers=headers) | |
| if resp.status_code == 200: | |
| logger.info("self-ping successful: %s", url) | |
| else: | |
| logger.warning("self-ping returned: %s β %s", url, resp.status_code) | |
| except Exception as exc: # noqa: BLE001 β keep the loop alive | |
| logger.warning("self-ping error: %s", exc) | |
| await asyncio.sleep(interval) | |
| async def lifespan(app: FastAPI): | |
| logger.info("app starting", extra={"version": settings.app_version}) | |
| # sampler_task = asyncio.create_task(system_sampler()) | |
| # broadcast_task = asyncio.create_task( | |
| # ws_manager.broadcast_loop(get_snapshot) | |
| # ) | |
| if settings.self_ping_enabled: | |
| logger.info( | |
| "scheduling self-ping task -> %s (every %ss)", | |
| settings.effective_self_ping_url, | |
| settings.self_ping_interval, | |
| ) | |
| asyncio.create_task(_self_ping()) | |
| else: | |
| logger.info("self-ping disabled (SELF_PING_ENABLED=false) β not scheduling") | |
| if settings.cron_enabled: | |
| logger.info( | |
| "scheduling frontend credit crons -> %s/api/cron + %s/api/v1/cron (daily 00:00)", | |
| (settings.frontend_base_url or "").rstrip("/") or "(FRONTEND_BASE_URL missing)", | |
| (settings.frontend_base_url or "").rstrip("/") or "(FRONTEND_BASE_URL missing)", | |
| ) | |
| else: | |
| logger.info("frontend credit crons disabled (CRON_ENABLED=false) β not scheduling /api/cron nor /api/v1/cron") | |
| cron_scheduler = start_cron_scheduler() | |
| if cron_scheduler is None: | |
| logger.warning("frontend credit cron scheduler NOT running β /api/cron and /api/v1/cron will not fire (see reason above)") | |
| yield | |
| if cron_scheduler is not None: | |
| cron_scheduler.shutdown(wait=False) | |
| logger.info("cron scheduler stopped") | |
| # sampler_task.cancel() | |
| # broadcast_task.cancel() | |
| await shutdown() | |
| await close_db_pools() | |
| await close_mongo_clients() | |
| await get_redis().close() | |
| logger.info("app stopped") | |
| app = FastAPI( | |
| title=settings.app_name, | |
| version=settings.app_version, | |
| lifespan=lifespan, | |
| docs_url="/docs" if settings.debug else None, | |
| redoc_url="/redoc" if settings.debug else None, | |
| ) | |
| # Monitoring middleware β must be first to capture all requests | |
| # app.add_middleware(MonitoringMiddleware) | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=settings.allowed_origins, | |
| allow_credentials=False, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| register_exception_handlers(app) | |
| # app.include_router(monitoring_router) | |
| app.include_router(executor.router) | |
| app.include_router(csv_service.router) | |
| app.include_router(db.router) | |
| app.include_router(chatbot.router) | |
| app.include_router(interpreter.router) | |
| app.include_router(embeddings.router) | |
| app.include_router(files.router) | |
| app.include_router(report_jobs.router) | |
| app.include_router(db_sync_jobs.router) | |
| async def root() -> dict[str, str]: | |
| return {"message": f"{settings.app_name} is running"} | |
| async def health() -> dict[str, str]: | |
| return {"status": "ok"} | |