Source code for luna_tasks.crutches_on_wheels.web.docs_handler

# -*- coding: utf-8 -*-
"""Document File Handler

Module realizes doc file handler.
"""
from typing import Tuple, Optional

from sanic import response
from sanic.response import HTTPResponse

from .application import LunaApplication
from ..constants.paths import STATIC_ROOT
from ..errors.errors import Error
from ..errors.exception import VLException
from ..web.handlers import BaseHandler


[docs]class SpecDocumentsHandler(BaseHandler): """ Handler for getting openapi documentations from static directory """ #: (str): custom document name (used in luna-matcher-proxy service) _docName: Optional[str] = None @property def app(self) -> LunaApplication: """ Get application Returns: running application """ return self.request.app @property def config(self): """ Get running application config Returns: running application config """ return self.request.app.ctx.serviceConfig @property def docName(self): """ Current REST API document name getter. Returns: REST API document name except extension """ if self._docName is None: return self.request.app.name return self._docName
[docs] @classmethod def customise(cls, docName: Optional[str] = None): """ Handler customising method. Args: docName: document name to store Returns: the current handler class """ if docName is not None: cls._docName = docName return cls
[docs] def getDataFromStatic(self, extension: str) -> Tuple[str, bytes]: """ Get file body from a static directory with the specified extension Args: extension: extension for document file (html or yml) Returns: tuple (filename, document body) """ if STATIC_ROOT.exists(): for posixPath in STATIC_ROOT.iterdir(): if self.docName + extension == posixPath.name: data = posixPath.read_bytes() return posixPath.name, data raise VLException(Error.DocumentNotFoundError, 500, isCriticalError=False) raise VLException(Error.StaticNotFoundError, 500, isCriticalError=False)
[docs] async def get(self) -> HTTPResponse: # pylint: disable-msg=W0221 """ Get document of services, see `get spec docs`_. .. _get spec docs: _static/api.html#operation/getSpec Resource is reached by address '/docs/spec' Raises: VLException(Error.UnsupportedMediaType, 415, isCriticalError=False), if "Accept" header is incorrect """ acceptHeaders = self.request.headers.get("Accept", "text/html").split(",") if "text/html" in acceptHeaders: contentType, extensionFile = "text/html", ".html" elif "application/x-yaml" in acceptHeaders: contentType, extensionFile = "application/x-yaml", ".yml" # Remove RAML extension when all services will use OpenApi if self.request.app.name in ("luna-index-manager",): extensionFile = ".raml" else: raise VLException(Error.UnsupportedMediaType, 415, isCriticalError=False) filename, fileBody = self.getDataFromStatic(extensionFile) return self.success( body=fileBody, extraHeaders={"Content-Disposition": f"inline; filename={filename}"}, contentType=contentType, )
[docs]class DevelopmentManualHandler(BaseHandler): """ Handler for getting sphinx documentations from static directory """ @property def app(self) -> LunaApplication: """ Get application Returns: running application """ return self.request.app @property def config(self): """ Get running application config Returns: running application config """ return self.request.app.ctx.serviceConfig
[docs] async def get(self): # pylint: disable-msg=W0221 """ Get `Sphinx` service documentation, see `get dev manual`_. .. _get dev manual: _static/api.html#operation/getDevManual Resource is reached by address '/docs/dev' """ apiVersion = self.request.app.ctx.apiVersion return response.redirect(f"/{apiVersion}/docs/dev/index.html")
[docs]def addDocHandlersRoutes(app: LunaApplication, specDocName: Optional[str] = None): """ Add standard docs handlers (OpenAPI and sphinx) to app Args: app: application specDocName: custom spec doc name """ app.add_route(DevelopmentManualHandler.as_view(), rf"/{app.ctx.apiVersion}/docs/dev", strict_slashes=True) app.add_route(DevelopmentManualHandler.as_view(), rf"/{app.ctx.apiVersion}/docs/dev/", strict_slashes=True) app.static(rf"/{app.ctx.apiVersion}/docs/dev", STATIC_ROOT / "sphinx", strict_slashes=False) SpecDocumentsHandler.customise(specDocName) app.add_route(SpecDocumentsHandler.as_view(), rf"/{app.ctx.apiVersion}/docs/spec", strict_slashes=False)