import json import logging import secrets from app.config import settings from app.middleware import block_scanners from app.v1.api import api_router from fastapi import Depends, FastAPI, HTTPException, status from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html from fastapi.security import HTTPBasic, HTTPBasicCredentials # --- Logging da aplicacao --- # Sem isto, os logging.info(...) das rotas sao engolidos: o root logger vem em # WARNING por padrao, entao INFO nao aparece no `podman logs`. logging.basicConfig( level=settings.log_level, format="%(asctime)s %(levelname)s %(message)s", ) # Filtra o acesso do healthcheck (/health a cada 30s) pra nao poluir o log. class _FiltraHealthAccess(logging.Filter): def filter(self, record: logging.LogRecord) -> bool: return "/health" not in record.getMessage() logging.getLogger("uvicorn.access").addFilter(_FiltraHealthAccess()) is_prod = settings.api.ambiente.lower() == "prod" app = FastAPI( title='API - Scardua', version='0.0.1', docs_url=None, redoc_url=None, openapi_url=None, ) app.middleware("http")(block_scanners) app.include_router(api_router, prefix="/v1") # --- Documentação protegida por login/senha (somente fora de produção) --- if not is_prod: _docs_security = HTTPBasic() def _verificar_docs( credenciais: HTTPBasicCredentials = Depends(_docs_security), ) -> str: usuario_ok = secrets.compare_digest( credenciais.username.encode("utf-8"), settings.docs.user.encode("utf-8"), ) senha_ok = secrets.compare_digest( credenciais.password.encode("utf-8"), settings.docs.password.encode("utf-8"), ) if not (usuario_ok and senha_ok): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Credenciais inválidas", headers={"WWW-Authenticate": "Basic"}, ) return credenciais.username @app.get("/openapi.json", include_in_schema=False) def _openapi_protegido(_: str = Depends(_verificar_docs)): return app.openapi() @app.get("/docs", include_in_schema=False) def _swagger_protegido(_: str = Depends(_verificar_docs)): return get_swagger_ui_html(openapi_url="/openapi.json", title=app.title) @app.get("/redoc", include_in_schema=False) def _redoc_protegido(_: str = Depends(_verificar_docs)): return get_redoc_html(openapi_url="/openapi.json", title=app.title) @app.get("/health", include_in_schema=False) def health(): """Healthcheck usado pelo Podman (auto-update / rollback).""" return {"status": "ok"} @app.post('/dados_retorno') def dados_retorno(dados_retorno: dict): """ Rota para vizualizar qualquer retorno do holmes """ logging.info("Dados retornados do teste") logging.info(json.dumps(dados_retorno, ensure_ascii=False)) return dados_retorno if __name__ == "__main__": import uvicorn port = settings.api.port ambiente = settings.api.ambiente workers = settings.api.workers is_reload = ambiente.lower() != "prod" logging.info("API ligada.") uvicorn.run( "main:app", host="0.0.0.0", port=port, log_level="info", workers=workers, reload=is_reload, )