Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add global try/except for requests #62

Merged
merged 3 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 54 additions & 30 deletions qsa-api/qsa_api/api/instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -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("/<instance>")
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("/<instance>/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("/<instance>/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
159 changes: 86 additions & 73 deletions qsa-api/qsa_api/api/processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -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/<project>")
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/<project>/<layer>")
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
Loading
Loading