From da204f5df8a0602e5857b9e9244d5c81e65ac99c Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Mon, 13 Sep 2021 09:54:53 +0200 Subject: [PATCH] better exceptions --- app/__init__.py | 21 +++++++++++---------- app/scodoc/sco_exceptions.py | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 1f68d0f5..cc09b792 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -12,7 +12,7 @@ from logging.handlers import SMTPHandler, WatchedFileHandler from flask import current_app, g, request from flask import Flask -from flask import abort, has_request_context +from flask import abort, has_request_context, jsonify from flask import render_template from flask.logging import default_handler from flask_sqlalchemy import SQLAlchemy @@ -24,7 +24,7 @@ from flask_moment import Moment from flask_caching import Cache import sqlalchemy -from app.scodoc.sco_exceptions import ScoValueError +from app.scodoc.sco_exceptions import ScoValueError, APIInvalidParams from config import DevConfig import sco_version @@ -56,6 +56,12 @@ def internal_server_error(e): return render_template("error_500.html", SCOVERSION=sco_version.SCOVERSION), 500 +def handle_invalid_usage(error): + response = jsonify(error.to_dict()) + response.status_code = error.status_code + return response + + def render_raw_html(template_filename: str, **args) -> str: """Load and render an HTML file _without_ using Flask Necessary for 503 error mesage, when DB is down and Flask may be broken. @@ -94,13 +100,8 @@ class ScoSMTPHandler(SMTPHandler): def getSubject(self, record: logging.LogRecord) -> str: stack_summary = traceback.extract_tb(record.exc_info[2]) frame_summary = stack_summary[-1] - subject = f"Sco Exc: {record.exc_info[0].__name__} in {frame_summary.name} {frame_summary.filename}" - # stack_summary.reverse() - # with open("/tmp/looooo", "wt") as f: - # for frame_summary in stack_summary: - # f.write( - # f"{record.exc_info[0].__name__} in {frame_summary.name} {frame_summary.filename}\n" - # ) + subject = f"ScoExc({sco_version.SCOVERSION}): {record.exc_info[0].__name__} in {frame_summary.name} {frame_summary.filename}" + return subject @@ -121,6 +122,7 @@ def create_app(config_class=DevConfig): app.register_error_handler(ScoValueError, handle_sco_value_error) app.register_error_handler(500, internal_server_error) app.register_error_handler(503, postgresql_server_error) + app.register_error_handler(APIInvalidParams, handle_invalid_usage) from app.auth import bp as auth_bp @@ -168,7 +170,6 @@ def create_app(config_class=DevConfig): mailhost=(app.config["MAIL_SERVER"], app.config["MAIL_PORT"]), fromaddr="no-reply@" + app.config["MAIL_SERVER"], toaddrs=["exception@scodoc.org"], - subject="ScoDoc Exception from " + host_name, credentials=auth, secure=secure, ) diff --git a/app/scodoc/sco_exceptions.py b/app/scodoc/sco_exceptions.py index 12aa05a1..5ae9ace4 100644 --- a/app/scodoc/sco_exceptions.py +++ b/app/scodoc/sco_exceptions.py @@ -96,3 +96,20 @@ class ScoGenError(ScoException): class ScoInvalidDateError(ScoValueError): pass + + +# Pour les API JSON +class APIInvalidParams(Exception): + status_code = 400 + + def __init__(self, message, status_code=None, payload=None): + Exception.__init__(self) + self.message = message + if status_code is not None: + self.status_code = status_code + self.payload = payload + + def to_dict(self): + rv = dict(self.payload or ()) + rv["message"] = self.message + return rv