"""Application Handlers. Requests are redirected to handlers, which are responsible for getting information from the URL and passing it down to the logic layer. The way each layer talks to each other is through Response objects which defines the type status of the data and the data itself. Please note: the Orchard uses the term handlers over views as convention for clarity See: gridgen.response for more details. """ from flask import Response, g from owsresponse import response from owsresponse.adaptors.flask import flaskify from werkzeug.exceptions import HTTPException from gridgen import config from gridgen.api import app from gridgen.exceptions import ValidateInternalError, ValidateNotFoundError from gridgen.logic import manager @app.route(config.HEALTH_CHECK) def health() -> Response: """Check the health of the application. Returns: flask.Response: the status of the service. """ return flaskify(response.Response({"status": "ok"})) @app.route("/release/", methods=["GET"]) def verify(release_id: int) -> Response: """Verify status of UPC. Args: release_id (int): unique id of release Returns: flask.Response: the status of the release """ g.log.debug("verify: GET /release/: release_id={}".format(release_id)) try: result = manager.validate(release_id) return flaskify(response.Response(message=result)) except (ValidateInternalError, ValidateNotFoundError) as e: return flaskify(response.Response(message=e.result, status=e.code)) @app.route("/release/", methods=["POST"]) def populate(release_id: int) -> Response: """Populate GRids for release identified by UPC. Args: release_id (int): unique id of release Returns: flask.Response: the status of the release """ g.log.debug( "populate: POST /release/: release_id={}".format(release_id) ) upc = manager.synchronize(release_id) if not upc: return flaskify(response.Response("", None, 204)) return flaskify(response.Response(f"{upc} processed for sync.")) @app.errorhandler(Exception) def exception_handler(exc: Exception) -> Response: """Default handler when uncaught exception is raised. Note: Exception will also be sent to Sentry if config.SENTRY is set. Returns: Response: A 500 response with error message. """ message = ( "The server encountered an internal error " "and was unable to complete your request." ) g.log.exception(exc) return flaskify(response.create_fatal_response(message=message)) @app.errorhandler(HTTPException) def http_exception_handler(exc: HTTPException) -> Response: """Handle error when HTTPException is raised. Returns: flask.Response: response with corresponding status code and error message from the exception. """ if exc.code == 404: app.logger.info(exc) code = response.error.ERROR_CODE_NOT_FOUND else: app.logger.exception(exc) code = exc.name.replace(" ", "_").lower() return flaskify( response.create_error_response( code=code, message=exc.description, status=(exc.code if exc.code else 500), ) )