diff --git a/openflexure_microscope/api/app.py b/openflexure_microscope/api/app.py index 44659886..205e9333 100644 --- a/openflexure_microscope/api/app.py +++ b/openflexure_microscope/api/app.py @@ -23,7 +23,7 @@ import os from datetime import datetime import pkg_resources -from flask import abort, send_file +from flask import abort, send_file, jsonify from flask_cors import CORS, cross_origin from labthings import create_app from labthings.extensions import find_extensions @@ -105,6 +105,19 @@ app, labthing = create_app( # Enable CORS for some routes outside of LabThings cors: CORS = CORS(app) +# Enable correct handling of Marshmallow/Webargs validation errors +# Return validation errors as JSON +# (see https://webargs.readthedocs.io/en/latest/framework_support.html) +@app.errorhandler(422) +@app.errorhandler(400) +def handle_error(err): + headers = err.data.get("headers", None) + messages = err.data.get("messages", ["Invalid request."]) + if headers: + return jsonify({"errors": messages}), err.code, headers + else: + return jsonify({"errors": messages}), err.code + # Use custom JSON encoder labthing.json_encoder = JSONEncoder app.json_encoder = JSONEncoder diff --git a/openflexure_microscope/api/default_extensions/scan.py b/openflexure_microscope/api/default_extensions/scan.py index 5a2365c4..e05f7352 100644 --- a/openflexure_microscope/api/default_extensions/scan.py +++ b/openflexure_microscope/api/default_extensions/scan.py @@ -2,6 +2,7 @@ import datetime import logging import time import uuid +import marshmallow from functools import reduce from typing import Dict, List, Optional, Tuple @@ -361,7 +362,7 @@ class ScanExtension(BaseExtension): class TileScanArgs(FullCaptureArgs): namemode = fields.String(missing="coordinates", example="coordinates") - grid = fields.List(fields.Integer, missing=[3, 3, 3], example=[3, 3, 3]) + grid = fields.List(fields.Integer(validate=marshmallow.validate.Range(min=1)), missing=[3, 3, 3], example=[3, 3, 3], ) style = fields.String(missing="raster") autofocus_dz = fields.Integer(missing=50) fast_autofocus = fields.Boolean(missing=False)