Files
2024-02-15 00:17:51 +03:30

113 lines
3.0 KiB
Python

import pathlib
from functools import lru_cache
import toml
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from fastapi.openapi.docs import get_redoc_html
from fastapi.openapi.utils import get_openapi
from fastapi.staticfiles import StaticFiles
from starlette import status
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import JSONResponse
from config import conf
from core.app.context import useAppContext
from core.app.docs import get_spotlight_docs
app = FastAPI(debug=True, root_path=conf.server.base_api_doc_url)
app.state = useAppContext()
# mount and map static directory
for _route, _dir in conf.static_files.items():
app.mount(f'{conf.server.prefix_url}/{_route}',
StaticFiles(directory=_dir), name=_dir)
def _parse_toml(pyproject_path):
pyproject_text = pyproject_path.read_text()
pyproject_data = toml.loads(pyproject_text)
info = pyproject_data['tool']['poetry']
setup_data = {
'name': info.get('name', 'No Name'),
'version': info.get('version', 'No version'),
'description': info.get('description', 'No description'),
'authors': info.get('authors', ['None']),
}
return setup_data
def get_pkg_info():
pyproject_path = pathlib.Path('pyproject.toml')
return _parse_toml(pyproject_path)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc: RequestValidationError):
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content=jsonable_encoder({"data": exc.errors(), "message": 'Validation error', 'code': 422}),
)
@app.get('/ping')
def ping():
return {"message": "pong", 'api_version': 2, "production": conf.server.is_prod, **get_pkg_info()}
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
info = get_pkg_info()
openapi_schema = get_openapi(
title=f'{info.get("name")} Api Documents',
version=info.get("version"),
description=info.get("description"),
routes=app.routes,
)
openapi_schema["info"]["x-logo"] = {
"url": conf.server.api_logo
}
app.openapi_schema = openapi_schema
return app.openapi_schema
@app.get("/redoc", include_in_schema=False)
async def redoc_html():
info = get_pkg_info()
return get_redoc_html(
openapi_url=app.openapi_url,
title=info.get('name') + " - ReDoc",
)
@app.get("/docu", include_in_schema=False)
async def docu():
info = get_pkg_info()
return get_spotlight_docs(
openapi_url=app.openapi_url,
title=info.get('name') + " - Docu",
)
app.openapi = custom_openapi
@lru_cache()
def load_origins():
return conf.cors.origins or []
app.add_middleware(
CORSMiddleware,
allow_origins=load_origins(),
allow_credentials=conf.cors.allow_credentials,
allow_methods=conf.cors.allow_methods,
allow_headers=conf.cors.allow_headers,
)
app.router.redirect_slashes = False