diff --git a/qsa-api/qsa_api/api/instances.py b/qsa-api/qsa_api/api/instances.py index 91d0b63..9df0280 100644 --- a/qsa-api/qsa_api/api/instances.py +++ b/qsa-api/qsa_api/api/instances.py @@ -4,62 +4,86 @@ from flask import current_app from datetime import datetime +from ..utils import logger +from .utils import log_request + + instances = Blueprint("instances", __name__) @instances.get("/") def instances_list(): - monitor = current_app.config["MONITOR"] + log_request() + try: + monitor = current_app.config["MONITOR"] - if not monitor: - return {"error": "QGIS Server monitoring is not activated"}, 415 + if not monitor: + return {"error": "QGIS Server monitoring is not activated"}, 415 - conns = {"servers": []} - for uid in monitor.conns: - info = {} - info["id"] = uid - info["ip"] = monitor.conns[uid].ip + conns = {"servers": []} + for uid in monitor.conns: + info = {} + info["id"] = uid + info["ip"] = monitor.conns[uid].ip - d = datetime.now() - monitor.conns[uid].now - info["binded"] = int(d.total_seconds()) - conns["servers"].append(info) - return conns + d = datetime.now() - monitor.conns[uid].now + info["binded"] = int(d.total_seconds()) + conns["servers"].append(info) + return conns + except Exception as e: + logger().exception(str(e)) + return {"error": "internal server error"}, 415 @instances.get("/") def instances_metadata(instance): - monitor = current_app.config["MONITOR"] + log_request() + try: + monitor = current_app.config["MONITOR"] - if not monitor: - return {"error": "QGIS Server monitoring is not activated"}, 415 + if not monitor: + return {"error": "QGIS Server monitoring is not activated"}, 415 - if instance not in monitor.conns: - return {"error": "QGIS Server instance is not available"}, 415 + if instance not in monitor.conns: + return {"error": "QGIS Server instance is not available"}, 415 - return monitor.conns[instance].metadata + return monitor.conns[instance].metadata + except Exception as e: + logger().exception(str(e)) + return {"error": "internal server error"}, 415 @instances.get("//logs") def instances_logs(instance): - monitor = current_app.config["MONITOR"] + log_request() + try: + monitor = current_app.config["MONITOR"] - if not monitor: - return {"error": "QGIS Server monitoring is not activated"}, 415 + if not monitor: + return {"error": "QGIS Server monitoring is not activated"}, 415 - if instance not in monitor.conns: - return {"error": "QGIS Server instance is not available"}, 415 + if instance not in monitor.conns: + return {"error": "QGIS Server instance is not available"}, 415 - return monitor.conns[instance].logs + return monitor.conns[instance].logs + except Exception as e: + logger().exception(str(e)) + return {"error": "internal server error"}, 415 @instances.get("//stats") def instances_stats(instance): - monitor = current_app.config["MONITOR"] + log_request() + try: + monitor = current_app.config["MONITOR"] - if not monitor: - return {"error": "QGIS Server monitoring is not activated"}, 415 + if not monitor: + return {"error": "QGIS Server monitoring is not activated"}, 415 - if instance not in monitor.conns: - return {"error": "QGIS Server instance is not available"}, 415 + if instance not in monitor.conns: + return {"error": "QGIS Server instance is not available"}, 415 - return monitor.conns[instance].stats + return monitor.conns[instance].stats + except Exception as e: + logger().exception(str(e)) + return {"error": "internal server error"}, 415 diff --git a/qsa-api/qsa_api/api/processing.py b/qsa-api/qsa_api/api/processing.py index 21478ee..9a0d5fb 100644 --- a/qsa-api/qsa_api/api/processing.py +++ b/qsa-api/qsa_api/api/processing.py @@ -4,92 +4,105 @@ from flask import Blueprint, jsonify, request from jsonschema.exceptions import ValidationError +from ..utils import logger from ..project import QSAProject from ..processing import RasterCalculator, Histogram +from .utils import log_request + processing = Blueprint("processing", __name__) @processing.post("/raster/calculator/") def raster_calculator(project: str): - schema = { - "type": "object", - "required": ["expression", "output"], - "properties": { - "expression": {"type": "string"}, - "output": {"type": "string"}, - }, - } - - data = request.get_json() + log_request() try: - validate(data, schema) - except ValidationError as e: - return {"error": e.message}, 415 - - expression = data["expression"] - output = data["output"] - - psql_schema = request.args.get("schema", default="public") - proj = QSAProject(project, psql_schema) - - if not proj.exists(): - return {"error": "Project doesn't exist"}, 415 - - calc = RasterCalculator(proj._qgis_project_uri, expression) - if not calc.is_valid(): - return {"error": "Invalid expression"}, 415 - - rc, msg = calc.process(output) - if not rc: - return { - "error": f"Raster calculator failed to process expression ({msg})" - }, 415 - - return jsonify(rc), 201 + schema = { + "type": "object", + "required": ["expression", "output"], + "properties": { + "expression": {"type": "string"}, + "output": {"type": "string"}, + }, + } + + data = request.get_json() + try: + validate(data, schema) + except ValidationError as e: + return {"error": e.message}, 415 + + expression = data["expression"] + output = data["output"] + + psql_schema = request.args.get("schema", default="public") + proj = QSAProject(project, psql_schema) + + if not proj.exists(): + return {"error": "Project doesn't exist"}, 415 + + calc = RasterCalculator(proj._qgis_project_uri, expression) + if not calc.is_valid(): + return {"error": "Invalid expression"}, 415 + + rc, msg = calc.process(output) + if not rc: + return { + "error": f"Raster calculator failed to process expression ({msg})" + }, 415 + + return jsonify(rc), 201 + except Exception as e: + logger().exception(str(e)) + return {"error": "internal server error"}, 415 @processing.post("/raster/histogram//") def raster_histogram(project: str, layer: str): - schema = { - "type": "object", - "properties": { - "min": {"type": "number"}, - "max": {"type": "number"}, - "count": {"type": "number"}, - }, - } - - data = request.get_json() + log_request() try: - validate(data, schema) - except ValidationError as e: - return {"error": e.message}, 415 - - mini = None - if "min" in data: - mini = data["min"] - - maxi = None - if "max" in data: - maxi = data["max"] - - count = 1000 - if "count" in data: - count = data["count"] - - proj = QSAProject(project) - if proj.exists(): - layer_infos = proj.layer(layer) - if layer_infos: - if "type" in layer_infos and layer_infos["type"] != "raster": - return { - "error": "Histogram is available for raster layer only" - } - histo = Histogram(proj._qgis_project_uri, layer) - return jsonify(histo.process(mini, maxi, count)), 201 + schema = { + "type": "object", + "properties": { + "min": {"type": "number"}, + "max": {"type": "number"}, + "count": {"type": "number"}, + }, + } + + data = request.get_json() + try: + validate(data, schema) + except ValidationError as e: + return {"error": e.message}, 415 + + mini = None + if "min" in data: + mini = data["min"] + + maxi = None + if "max" in data: + maxi = data["max"] + + count = 1000 + if "count" in data: + count = data["count"] + + proj = QSAProject(project) + if proj.exists(): + layer_infos = proj.layer(layer) + if layer_infos: + if "type" in layer_infos and layer_infos["type"] != "raster": + return { + "error": "Histogram is available for raster layer only" + } + histo = Histogram(proj._qgis_project_uri, layer) + return jsonify(histo.process(mini, maxi, count)), 201 + else: + return {"error": "Layer does not exist"}, 415 else: - return {"error": "Layer does not exist"}, 415 - else: - return {"error": "Project does not exist"}, 415 + return {"error": "Project does not exist"}, 415 + except Exception as e: + logger().exception(str(e)) + return {"error": "internal server error"}, 415 diff --git a/qsa-api/qsa_api/api/projects.py b/qsa-api/qsa_api/api/projects.py index 2e302fa..c563d51 100644 --- a/qsa-api/qsa_api/api/projects.py +++ b/qsa-api/qsa_api/api/projects.py @@ -9,340 +9,430 @@ from qgis.PyQt.QtCore import QDateTime from ..wms import WMS +from ..utils import logger from ..project import QSAProject +from .utils import log_request + projects = Blueprint("projects", __name__) @projects.get("/") def projects_list(): - psql_schema = request.args.get("schema", default="public") + log_request() + try: + psql_schema = request.args.get("schema", default="public") - p = [] - for project in QSAProject.projects(psql_schema): - p.append(project.name) - return jsonify(p) + p = [] + for project in QSAProject.projects(psql_schema): + p.append(project.name) + return jsonify(p) + except Exception as e: + logger().exception(str(e)) + return {"error": "internal server error"}, 415 @projects.get("/") def project_info(name: str): - psql_schema = request.args.get("schema", default="public") - project = QSAProject(name, psql_schema) + log_request() + try: + psql_schema = request.args.get("schema", default="public") + project = QSAProject(name, psql_schema) - if project.exists(): - return jsonify(project.metadata) - return {"error": "Project does not exist"}, 415 + if project.exists(): + return jsonify(project.metadata) + return {"error": "Project does not exist"}, 415 + except Exception as e: + logger().exception(str(e)) + return {"error": "internal server error"}, 415 @projects.post("/") def project_add(): - schema = { - "type": "object", - "required": ["name", "author"], - "properties": { - "name": {"type": "string"}, - "author": {"type": "string"}, - "schema": {"type": "string"}, - }, - } - - if request.is_json: - data = request.get_json() - try: - validate(data, schema) - except ValidationError as e: - return {"error": e.message}, 415 - - name = data["name"] - author = data["author"] - schema = "" - if "schema" in data: - schema = data["schema"] - - project = QSAProject(name, schema) - if project.exists(): - return {"error": "Project already exists"} - rc, err = project.create(author) - if not rc: - return {"error": err}, 415 - return jsonify(True), 201 - return {"error": "Request must be JSON"}, 415 + log_request() + try: + schema = { + "type": "object", + "required": ["name", "author"], + "properties": { + "name": {"type": "string"}, + "author": {"type": "string"}, + "schema": {"type": "string"}, + }, + } + + if request.is_json: + data = request.get_json() + try: + validate(data, schema) + except ValidationError as e: + return {"error": e.message}, 415 + + name = data["name"] + author = data["author"] + schema = "" + if "schema" in data: + schema = data["schema"] + + project = QSAProject(name, schema) + if project.exists(): + return {"error": "Project already exists"} + rc, err = project.create(author) + if not rc: + return {"error": err}, 415 + return jsonify(True), 201 + return {"error": "Request must be JSON"}, 415 + except Exception as e: + logger().exception(str(e)) + return {"error": "internal server error"}, 415 @projects.delete("/") def project_del(name): - psql_schema = request.args.get("schema", default="public") - project = QSAProject(name, psql_schema) + log_request() + try: + psql_schema = request.args.get("schema", default="public") + project = QSAProject(name, psql_schema) - if project.exists(): - project.remove() - return jsonify(True), 201 - return {"error": "Project does not exist"}, 415 + if project.exists(): + project.remove() + return jsonify(True), 201 + return {"error": "Project does not exist"}, 415 + except Exception as e: + logger().exception(str(e)) + return {"error": "internal server error"}, 415 @projects.get("//styles") def project_styles(name): - psql_schema = request.args.get("schema", default="public") - project = QSAProject(name, psql_schema) - if project.exists(): - return jsonify(project.styles), 201 - else: - return {"error": "Project does not exist"}, 415 + log_request() + try: + psql_schema = request.args.get("schema", default="public") + project = QSAProject(name, psql_schema) + if project.exists(): + return jsonify(project.styles), 201 + else: + return {"error": "Project does not exist"}, 415 + except Exception as e: + logger().exception(str(e)) + return {"error": "internal server error"}, 415 @projects.get("//styles/