Initial commit
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
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
|
||||
@@ -0,0 +1,13 @@
|
||||
from starlette.datastructures import State
|
||||
from starlette.requests import Request
|
||||
|
||||
|
||||
class AppContext(State):
|
||||
request: Request
|
||||
|
||||
|
||||
app_context = AppContext()
|
||||
|
||||
|
||||
def useAppContext() -> AppContext:
|
||||
return app_context
|
||||
@@ -0,0 +1,26 @@
|
||||
from starlette.responses import HTMLResponse
|
||||
|
||||
|
||||
def get_spotlight_docs(title, openapi_url):
|
||||
html = f"""
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>{title}</title>
|
||||
|
||||
<script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<elements-api
|
||||
apiDescriptionUrl="{openapi_url}"
|
||||
router="hash"
|
||||
/>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
return HTMLResponse(html)
|
||||
Reference in New Issue
Block a user