Files
projects/Dockers/puppeteer-api/app/main.py
T
Bram 09ecad1e7c
Build and Push Docker Images / build-and-push (push) Successful in 4m10s
add swagger to puppeteer
2026-04-23 15:21:50 +02:00

114 lines
3.5 KiB
Python

from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi
from fastapi.security import APIKeyHeader
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
from app.database import init_db, cleanup_old_cache_entries
from app.config import CLEANUP_CRON, CACHE_EXPIRY_HOURS
from app.routes import health, browser, cache
from app.services.browser import force_cleanup_old_pages
from pathlib import Path
def _read_version() -> str:
version_file = Path(__file__).resolve().parents[1] / "version"
try:
v = version_file.read_text(encoding="utf-8").strip()
return v or "latest"
except Exception:
return "latest"
API_KEY_HEADER_NAME = "X-API-Key"
api_key_header = APIKeyHeader(name=API_KEY_HEADER_NAME, auto_error=False)
# Create FastAPI app
app = FastAPI(
title="Playwright API Server",
version=_read_version(),
description=(
"FastAPI server that uses Playwright to visit pages, capture screenshots, "
"extract SEO/meta information, and manage a cache.\n\n"
f"Authentication: provide `{API_KEY_HEADER_NAME}` on requests."
),
docs_url="/docs",
redoc_url="/redoc",
openapi_url="/openapi.json",
swagger_ui_parameters={"persistAuthorization": True},
)
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title=app.title,
version=app.version,
description=app.description,
routes=app.routes,
)
components = openapi_schema.setdefault("components", {})
security_schemes = components.setdefault("securitySchemes", {})
security_schemes["ApiKeyAuth"] = {
"type": "apiKey",
"in": "header",
"name": API_KEY_HEADER_NAME,
"description": f"Send your API key in the `{API_KEY_HEADER_NAME}` header.",
}
# Apply API key auth globally (individual endpoints may still allow anonymous access;
# this just documents the expected auth mechanism).
openapi_schema["security"] = [{"ApiKeyAuth": []}]
openapi_schema["tags"] = [
{"name": "Health", "description": "Liveness / basic health checks."},
{"name": "Browser", "description": "Playwright-powered browsing utilities."},
{"name": "Cache", "description": "Cache management and statistics."},
]
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi
# Include routers
app.include_router(health.router, tags=["Health"])
app.include_router(browser.router, tags=["Browser"])
app.include_router(cache.router, tags=["Cache"])
# Initialize scheduler for periodic cache cleanup
scheduler = BackgroundScheduler()
scheduler.add_job(
cleanup_old_cache_entries,
CronTrigger.from_crontab(CLEANUP_CRON),
id='cache_cleanup_job',
replace_existing=True
)
# Add browser cleanup job
scheduler.add_job(
force_cleanup_old_pages,
CronTrigger.from_crontab(CLEANUP_CRON),
id='browser_cleanup_job',
replace_existing=True
)
# Initialize database on startup
init_db()
# Start the scheduler when the application starts
@app.on_event("startup")
def start_scheduler():
scheduler.start()
print(f"Cache cleanup scheduler started with cron: {CLEANUP_CRON}")
print(f"Cache entries will expire after {CACHE_EXPIRY_HOURS} hours")
print("Browser cleanup scheduler started")
# Shutdown the scheduler when the application stops
@app.on_event("shutdown")
def shutdown_scheduler():
scheduler.shutdown(wait=False)
print("Cache cleanup scheduler stopped")