mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
migrate api to module
This commit is contained in:
@@ -1,274 +0,0 @@
|
|||||||
"""hyperglass web app initiator."""
|
|
||||||
# Standard Library Imports
|
|
||||||
import os
|
|
||||||
import tempfile
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
# Third Party Imports
|
|
||||||
from fastapi import FastAPI
|
|
||||||
from fastapi import HTTPException
|
|
||||||
from fastapi.openapi.docs import get_redoc_html
|
|
||||||
from fastapi.openapi.docs import get_swagger_ui_html
|
|
||||||
from fastapi.openapi.utils import get_openapi
|
|
||||||
from prometheus_client import CONTENT_TYPE_LATEST
|
|
||||||
from prometheus_client import CollectorRegistry
|
|
||||||
from prometheus_client import Counter
|
|
||||||
from prometheus_client import generate_latest
|
|
||||||
from prometheus_client import multiprocess
|
|
||||||
from starlette.exceptions import HTTPException as StarletteHTTPException
|
|
||||||
from starlette.middleware.cors import CORSMiddleware
|
|
||||||
from starlette.requests import Request
|
|
||||||
from starlette.responses import PlainTextResponse
|
|
||||||
from starlette.responses import UJSONResponse
|
|
||||||
from starlette.staticfiles import StaticFiles
|
|
||||||
|
|
||||||
# Project Imports
|
|
||||||
from hyperglass.configuration import frontend_params
|
|
||||||
from hyperglass.configuration import params
|
|
||||||
from hyperglass.constants import __version__
|
|
||||||
from hyperglass.exceptions import HyperglassError
|
|
||||||
from hyperglass.models.query import Query
|
|
||||||
from hyperglass.models.response import QueryResponse
|
|
||||||
from hyperglass.query import REDIS_CONFIG
|
|
||||||
from hyperglass.query import handle_query
|
|
||||||
from hyperglass.util import build_frontend
|
|
||||||
from hyperglass.util import check_python
|
|
||||||
from hyperglass.util import check_redis
|
|
||||||
from hyperglass.util import clear_redis_cache
|
|
||||||
from hyperglass.util import log
|
|
||||||
|
|
||||||
STATIC_DIR = Path(__file__).parent / "static"
|
|
||||||
UI_DIR = STATIC_DIR / "ui"
|
|
||||||
IMAGES_DIR = STATIC_DIR / "images"
|
|
||||||
NEXT_DIR = UI_DIR / "_next"
|
|
||||||
INDEX = UI_DIR / "index.html"
|
|
||||||
|
|
||||||
STATIC_FILES = "\n".join([str(STATIC_DIR), str(UI_DIR), str(IMAGES_DIR), str(NEXT_DIR)])
|
|
||||||
|
|
||||||
log.debug(f"Static Files: {STATIC_FILES}")
|
|
||||||
|
|
||||||
# Main App Definition
|
|
||||||
app = FastAPI(
|
|
||||||
debug=params.general.debug,
|
|
||||||
title=params.general.site_title,
|
|
||||||
description=params.general.site_description,
|
|
||||||
version=__version__,
|
|
||||||
default_response_class=UJSONResponse,
|
|
||||||
docs_url=None,
|
|
||||||
redoc_url=None,
|
|
||||||
openapi_url=params.general.docs.openapi_url,
|
|
||||||
)
|
|
||||||
# app.mount("/ui", StaticFiles(directory=UI_DIR), name="ui")
|
|
||||||
# app.mount("/ui/images", StaticFiles(directory=IMAGES_DIR), name="ui/images")
|
|
||||||
app.mount("/_next", StaticFiles(directory=NEXT_DIR), name="_next")
|
|
||||||
app.mount("/images", StaticFiles(directory=IMAGES_DIR), name="images")
|
|
||||||
|
|
||||||
if params.general.docs.enable:
|
|
||||||
log.debug(f"API Docs config: {app.openapi()}")
|
|
||||||
|
|
||||||
DEV_URL = f"http://localhost:{str(params.general.listen_port)}/api/"
|
|
||||||
PROD_URL = "/api/"
|
|
||||||
|
|
||||||
CORS_ORIGINS = params.general.cors_origins.copy()
|
|
||||||
if params.general.developer_mode:
|
|
||||||
CORS_ORIGINS.append(DEV_URL)
|
|
||||||
|
|
||||||
# CORS Configuration
|
|
||||||
app.add_middleware(
|
|
||||||
CORSMiddleware,
|
|
||||||
allow_origins=CORS_ORIGINS,
|
|
||||||
allow_methods=["GET", "POST", "OPTIONS"],
|
|
||||||
allow_headers=["*"],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def custom_openapi():
|
|
||||||
"""Generate custom OpenAPI config."""
|
|
||||||
openapi_schema = get_openapi(
|
|
||||||
title=params.general.site_title,
|
|
||||||
version=__version__,
|
|
||||||
description=params.general.site_description,
|
|
||||||
routes=app.routes,
|
|
||||||
)
|
|
||||||
app.openapi_schema = openapi_schema
|
|
||||||
return app.openapi_schema
|
|
||||||
|
|
||||||
|
|
||||||
app.openapi = custom_openapi
|
|
||||||
|
|
||||||
ASGI_PARAMS = {
|
|
||||||
"host": str(params.general.listen_address),
|
|
||||||
"port": params.general.listen_port,
|
|
||||||
"debug": params.general.debug,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@app.on_event("startup")
|
|
||||||
async def check_python_version():
|
|
||||||
"""Ensure Python version meets minimum requirement.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
HyperglassError: Raised if Python version is invalid.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
python_version = check_python()
|
|
||||||
log.info(f"Python {python_version} detected")
|
|
||||||
except RuntimeError as r:
|
|
||||||
raise HyperglassError(str(r), alert="danger") from None
|
|
||||||
|
|
||||||
|
|
||||||
@app.on_event("startup")
|
|
||||||
async def check_redis_instance():
|
|
||||||
"""Ensure Redis is running before starting server.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
HyperglassError: Raised if Redis is not running.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
{bool} -- True if Redis is running.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
await check_redis(db=params.features.cache.redis_id, config=REDIS_CONFIG)
|
|
||||||
except RuntimeError as e:
|
|
||||||
raise HyperglassError(str(e), alert="danger") from None
|
|
||||||
|
|
||||||
log.debug(f"Redis is running at: {REDIS_CONFIG['host']}:{REDIS_CONFIG['port']}")
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
@app.on_event("startup")
|
|
||||||
async def build_ui():
|
|
||||||
"""Perform a UI build prior to starting the application.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
HTTPException: Raised if any build errors occur.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
{bool} -- True if successful.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
await build_frontend(
|
|
||||||
dev_mode=params.general.developer_mode,
|
|
||||||
dev_url=DEV_URL,
|
|
||||||
prod_url=PROD_URL,
|
|
||||||
params=frontend_params,
|
|
||||||
)
|
|
||||||
except RuntimeError as e:
|
|
||||||
raise HTTPException(detail=str(e), status_code=500)
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
@app.on_event("shutdown")
|
|
||||||
async def clear_cache():
|
|
||||||
"""Clear the Redis cache on shutdown."""
|
|
||||||
try:
|
|
||||||
await clear_redis_cache(db=params.features.cache.redis_id, config=REDIS_CONFIG)
|
|
||||||
except RuntimeError as e:
|
|
||||||
log.error(str(e))
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@app.exception_handler(StarletteHTTPException)
|
|
||||||
async def http_exception_handler(request, exc):
|
|
||||||
"""Handle web server errors."""
|
|
||||||
return UJSONResponse(
|
|
||||||
{"output": exc.detail, "alert": "danger", "keywords": []},
|
|
||||||
status_code=exc.status_code,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@app.exception_handler(HyperglassError)
|
|
||||||
async def app_exception_handler(request, exc):
|
|
||||||
"""Handle application errors."""
|
|
||||||
return UJSONResponse(
|
|
||||||
{"output": exc.message, "alert": exc.alert, "keywords": exc.keywords},
|
|
||||||
status_code=exc.status_code,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Prometheus Config
|
|
||||||
count_data = Counter(
|
|
||||||
"count_data", "Query Counter", ["source", "query_type", "loc_id", "target", "vrf"]
|
|
||||||
)
|
|
||||||
|
|
||||||
count_errors = Counter(
|
|
||||||
"count_errors",
|
|
||||||
"Error Counter",
|
|
||||||
["reason", "source", "query_type", "loc_id", "target"],
|
|
||||||
)
|
|
||||||
|
|
||||||
count_ratelimit = Counter(
|
|
||||||
"count_ratelimit", "Rate Limit Counter", ["message", "source"]
|
|
||||||
)
|
|
||||||
|
|
||||||
count_notfound = Counter(
|
|
||||||
"count_notfound", "404 Not Found Counter", ["message", "path", "source"]
|
|
||||||
)
|
|
||||||
|
|
||||||
tempdir = tempfile.TemporaryDirectory(prefix="hyperglass_")
|
|
||||||
os.environ["prometheus_multiproc_dir"] = tempdir.name
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/metrics", include_in_schema=False)
|
|
||||||
async def metrics(request):
|
|
||||||
"""Serve Prometheus metrics."""
|
|
||||||
registry = CollectorRegistry()
|
|
||||||
multiprocess.MultiProcessCollector(registry)
|
|
||||||
latest = generate_latest(registry)
|
|
||||||
return PlainTextResponse(
|
|
||||||
latest,
|
|
||||||
headers={
|
|
||||||
"Content-Type": CONTENT_TYPE_LATEST,
|
|
||||||
"Content-Length": str(len(latest)),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@app.post(
|
|
||||||
"/api/query/",
|
|
||||||
summary=params.general.docs.endpoint_summary,
|
|
||||||
description=params.general.docs.endpoint_description,
|
|
||||||
response_model=QueryResponse,
|
|
||||||
tags=[params.general.docs.group_title],
|
|
||||||
)
|
|
||||||
async def query(query_data: Query, request: Request):
|
|
||||||
"""Ingest request data pass it to the backend application to perform the query."""
|
|
||||||
|
|
||||||
# Get client IP address for Prometheus logging & rate limiting
|
|
||||||
client_addr = request.client.host
|
|
||||||
|
|
||||||
# Increment Prometheus counter
|
|
||||||
count_data.labels(
|
|
||||||
client_addr,
|
|
||||||
query_data.query_type,
|
|
||||||
query_data.query_location,
|
|
||||||
query_data.query_target,
|
|
||||||
query_data.query_vrf,
|
|
||||||
).inc()
|
|
||||||
|
|
||||||
log.debug(f"Client Address: {client_addr}")
|
|
||||||
|
|
||||||
response = await handle_query(query_data)
|
|
||||||
|
|
||||||
return UJSONResponse({"output": response}, status_code=200)
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/docs", include_in_schema=False)
|
|
||||||
async def docs():
|
|
||||||
"""Serve custom docs."""
|
|
||||||
if params.general.docs.enable:
|
|
||||||
docs_func_map = {"swagger": get_swagger_ui_html, "redoc": get_redoc_html}
|
|
||||||
docs_func = docs_func_map[params.general.docs.mode]
|
|
||||||
return docs_func(openapi_url=app.openapi_url, title=app.title + " - API Docs")
|
|
||||||
else:
|
|
||||||
raise HTTPException(detail="Not found", status_code=404)
|
|
||||||
|
|
||||||
|
|
||||||
app.mount("/", StaticFiles(directory=UI_DIR, html=True), name="ui")
|
|
||||||
|
|
||||||
|
|
||||||
def start():
|
|
||||||
"""Start the web server with Uvicorn ASGI."""
|
|
||||||
import uvicorn
|
|
||||||
|
|
||||||
uvicorn.run(app, **ASGI_PARAMS)
|
|
107
hyperglass/api/__init__.py
Normal file
107
hyperglass/api/__init__.py
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
"""hyperglass REST API & Web UI."""
|
||||||
|
|
||||||
|
# Standard Library Imports
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Third Party Imports
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from fastapi.openapi.utils import get_openapi
|
||||||
|
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||||
|
from starlette.middleware.cors import CORSMiddleware
|
||||||
|
from starlette.responses import UJSONResponse
|
||||||
|
from starlette.staticfiles import StaticFiles
|
||||||
|
|
||||||
|
# Project Imports
|
||||||
|
from hyperglass.api.error_handlers import app_handler
|
||||||
|
from hyperglass.api.error_handlers import http_handler
|
||||||
|
from hyperglass.api.events import on_shutdown
|
||||||
|
from hyperglass.api.events import on_startup
|
||||||
|
from hyperglass.api.routes import docs
|
||||||
|
from hyperglass.api.routes import query
|
||||||
|
from hyperglass.configuration import URL_DEV
|
||||||
|
from hyperglass.configuration import params
|
||||||
|
from hyperglass.constants import __version__
|
||||||
|
from hyperglass.exceptions import HyperglassError
|
||||||
|
from hyperglass.models.response import QueryResponse
|
||||||
|
from hyperglass.util import log
|
||||||
|
|
||||||
|
STATIC_DIR = Path(__file__).parent.parent / "static"
|
||||||
|
UI_DIR = STATIC_DIR / "ui"
|
||||||
|
IMAGES_DIR = STATIC_DIR / "images"
|
||||||
|
|
||||||
|
ASGI_PARAMS = {
|
||||||
|
"host": str(params.general.listen_address),
|
||||||
|
"port": params.general.listen_port,
|
||||||
|
"debug": params.general.debug,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main App Definition
|
||||||
|
app = FastAPI(
|
||||||
|
debug=params.general.debug,
|
||||||
|
title=params.general.site_title,
|
||||||
|
description=params.general.site_description,
|
||||||
|
version=__version__,
|
||||||
|
default_response_class=UJSONResponse,
|
||||||
|
docs_url=None,
|
||||||
|
redoc_url=None,
|
||||||
|
openapi_url=params.general.docs.openapi_url,
|
||||||
|
on_shutdown=on_shutdown,
|
||||||
|
on_startup=on_startup,
|
||||||
|
)
|
||||||
|
|
||||||
|
# HTTP Error Handler
|
||||||
|
app.add_exception_handler(StarletteHTTPException, http_handler)
|
||||||
|
|
||||||
|
# Backend Application Error Handler
|
||||||
|
app.add_exception_handler(HyperglassError, app_handler)
|
||||||
|
|
||||||
|
|
||||||
|
def _custom_openapi():
|
||||||
|
"""Generate custom OpenAPI config."""
|
||||||
|
openapi_schema = get_openapi(
|
||||||
|
title=params.general.site_title,
|
||||||
|
version=__version__,
|
||||||
|
description=params.general.site_description,
|
||||||
|
routes=app.routes,
|
||||||
|
)
|
||||||
|
app.openapi_schema = openapi_schema
|
||||||
|
return app.openapi_schema
|
||||||
|
|
||||||
|
|
||||||
|
app.openapi = _custom_openapi
|
||||||
|
|
||||||
|
if params.general.docs.enable:
|
||||||
|
log.debug(f"API Docs config: {app.openapi()}")
|
||||||
|
|
||||||
|
CORS_ORIGINS = params.general.cors_origins.copy()
|
||||||
|
if params.general.developer_mode:
|
||||||
|
CORS_ORIGINS.append(URL_DEV)
|
||||||
|
|
||||||
|
# CORS Configuration
|
||||||
|
app.add_middleware(
|
||||||
|
CORSMiddleware,
|
||||||
|
allow_origins=CORS_ORIGINS,
|
||||||
|
allow_methods=["GET", "POST", "OPTIONS"],
|
||||||
|
allow_headers=["*"],
|
||||||
|
)
|
||||||
|
|
||||||
|
app.add_api_route(
|
||||||
|
path="/api/query/",
|
||||||
|
endpoint=query,
|
||||||
|
methods=["POST"],
|
||||||
|
summary=params.general.docs.endpoint_summary,
|
||||||
|
description=params.general.docs.endpoint_description,
|
||||||
|
response_model=QueryResponse,
|
||||||
|
tags=[params.general.docs.group_title],
|
||||||
|
response_class=UJSONResponse,
|
||||||
|
)
|
||||||
|
app.add_api_route(path="api/docs", endpoint=docs, include_in_schema=False)
|
||||||
|
app.mount("/images", StaticFiles(directory=IMAGES_DIR), name="images")
|
||||||
|
app.mount("/", StaticFiles(directory=UI_DIR, html=True), name="ui")
|
||||||
|
|
||||||
|
|
||||||
|
def start():
|
||||||
|
"""Start the web server with Uvicorn ASGI."""
|
||||||
|
import uvicorn
|
||||||
|
|
||||||
|
uvicorn.run(app, **ASGI_PARAMS)
|
19
hyperglass/api/error_handlers.py
Normal file
19
hyperglass/api/error_handlers.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
"""API Error Handlers."""
|
||||||
|
# Third Party Imports
|
||||||
|
from starlette.responses import UJSONResponse
|
||||||
|
|
||||||
|
|
||||||
|
async def http_handler(request, exc):
|
||||||
|
"""Handle web server errors."""
|
||||||
|
return UJSONResponse(
|
||||||
|
{"output": exc.detail, "level": "danger", "keywords": []},
|
||||||
|
status_code=exc.status_code,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def app_handler(request, exc):
|
||||||
|
"""Handle application errors."""
|
||||||
|
return UJSONResponse(
|
||||||
|
{"output": exc.message, "level": exc.level, "keywords": exc.keywords},
|
||||||
|
status_code=exc.status_code,
|
||||||
|
)
|
81
hyperglass/api/events.py
Normal file
81
hyperglass/api/events.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
"""API Events."""
|
||||||
|
# Third Party Imports
|
||||||
|
from starlette.exceptions import HTTPException
|
||||||
|
|
||||||
|
# Project Imports
|
||||||
|
from hyperglass.configuration import URL_DEV
|
||||||
|
from hyperglass.configuration import URL_PROD
|
||||||
|
from hyperglass.configuration import frontend_params
|
||||||
|
from hyperglass.configuration import params
|
||||||
|
from hyperglass.exceptions import HyperglassError
|
||||||
|
from hyperglass.query import REDIS_CONFIG
|
||||||
|
from hyperglass.util import build_frontend
|
||||||
|
from hyperglass.util import check_python
|
||||||
|
from hyperglass.util import check_redis
|
||||||
|
from hyperglass.util import clear_redis_cache
|
||||||
|
from hyperglass.util import log
|
||||||
|
|
||||||
|
|
||||||
|
async def check_python_version():
|
||||||
|
"""Ensure Python version meets minimum requirement.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
HyperglassError: Raised if Python version is invalid.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
python_version = check_python()
|
||||||
|
log.info(f"Python {python_version} detected")
|
||||||
|
except RuntimeError as r:
|
||||||
|
raise HyperglassError(str(r), alert="danger") from None
|
||||||
|
|
||||||
|
|
||||||
|
async def check_redis_instance():
|
||||||
|
"""Ensure Redis is running before starting server.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
HyperglassError: Raised if Redis is not running.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
{bool} -- True if Redis is running.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
await check_redis(db=params.features.cache.redis_id, config=REDIS_CONFIG)
|
||||||
|
except RuntimeError as e:
|
||||||
|
raise HyperglassError(str(e), alert="danger") from None
|
||||||
|
|
||||||
|
log.debug(f"Redis is running at: {REDIS_CONFIG['host']}:{REDIS_CONFIG['port']}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def build_ui():
|
||||||
|
"""Perform a UI build prior to starting the application.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
HTTPException: Raised if any build errors occur.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
{bool} -- True if successful.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
await build_frontend(
|
||||||
|
dev_mode=params.general.developer_mode,
|
||||||
|
dev_url=URL_DEV,
|
||||||
|
prod_url=URL_PROD,
|
||||||
|
params=frontend_params,
|
||||||
|
)
|
||||||
|
except RuntimeError as e:
|
||||||
|
raise HTTPException(detail=str(e), status_code=500)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def clear_cache():
|
||||||
|
"""Clear the Redis cache on shutdown."""
|
||||||
|
try:
|
||||||
|
await clear_redis_cache(db=params.features.cache.redis_id, config=REDIS_CONFIG)
|
||||||
|
except RuntimeError as e:
|
||||||
|
log.error(str(e))
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
on_startup = [check_python_version, check_redis_instance, build_ui]
|
||||||
|
on_shutdown = [clear_cache]
|
@@ -1,36 +1,28 @@
|
|||||||
"""Hyperglass Front End."""
|
"""API Routes."""
|
||||||
|
|
||||||
# Standard Library Imports
|
# Standard Library Imports
|
||||||
import time
|
import time
|
||||||
|
|
||||||
# Third Party Imports
|
# Third Party Imports
|
||||||
import aredis
|
import aredis
|
||||||
|
from fastapi import HTTPException
|
||||||
|
from fastapi.openapi.docs import get_redoc_html
|
||||||
|
from fastapi.openapi.docs import get_swagger_ui_html
|
||||||
|
from starlette.requests import Request
|
||||||
|
|
||||||
# Project Imports
|
# Project Imports
|
||||||
|
from hyperglass.configuration import REDIS_CONFIG
|
||||||
from hyperglass.configuration import params
|
from hyperglass.configuration import params
|
||||||
from hyperglass.exceptions import HyperglassError
|
from hyperglass.exceptions import HyperglassError
|
||||||
from hyperglass.execution.execute import Execute
|
from hyperglass.execution.execute import Execute
|
||||||
|
from hyperglass.models.query import Query
|
||||||
from hyperglass.util import log
|
from hyperglass.util import log
|
||||||
|
|
||||||
log.debug(f"Configuration Parameters: {params.dict(by_alias=True)}")
|
|
||||||
|
|
||||||
# Redis Config
|
|
||||||
REDIS_CONFIG = {
|
|
||||||
"host": str(params.general.redis_host),
|
|
||||||
"port": params.general.redis_port,
|
|
||||||
"decode_responses": True,
|
|
||||||
}
|
|
||||||
|
|
||||||
Cache = aredis.StrictRedis(db=params.features.cache.redis_id, **REDIS_CONFIG)
|
Cache = aredis.StrictRedis(db=params.features.cache.redis_id, **REDIS_CONFIG)
|
||||||
|
|
||||||
|
|
||||||
async def handle_query(query_data):
|
async def query(query_data: Query, request: Request):
|
||||||
"""Process XHR POST data.
|
"""Ingest request data pass it to the backend application to perform the query."""
|
||||||
|
|
||||||
Ingests XHR POST data from
|
|
||||||
form submit, passes it to the backend application to perform the
|
|
||||||
filtering/lookups.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Use hashed query_data string as key for for k/v cache store so
|
# Use hashed query_data string as key for for k/v cache store so
|
||||||
# each command output value is unique.
|
# each command output value is unique.
|
||||||
@@ -67,4 +59,20 @@ async def handle_query(query_data):
|
|||||||
log.debug(f"Cache match for: {cache_key}, returning cached entry")
|
log.debug(f"Cache match for: {cache_key}, returning cached entry")
|
||||||
log.debug(f"Cache Output: {cache_response}")
|
log.debug(f"Cache Output: {cache_response}")
|
||||||
|
|
||||||
return cache_response
|
return {"output": cache_response, "level": "success", "keywords": []}
|
||||||
|
|
||||||
|
|
||||||
|
async def docs():
|
||||||
|
"""Serve custom docs."""
|
||||||
|
if params.general.docs.enable:
|
||||||
|
docs_func_map = {"swagger": get_swagger_ui_html, "redoc": get_redoc_html}
|
||||||
|
docs_func = docs_func_map[params.general.docs.mode]
|
||||||
|
return docs_func(
|
||||||
|
openapi_url=params.general.docs.openapi_url,
|
||||||
|
title=params.general.site_title + " - API Docs",
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise HTTPException(detail="Not found", status_code=404)
|
||||||
|
|
||||||
|
|
||||||
|
endpoints = [query, docs]
|
Reference in New Issue
Block a user