frompprintimportpformatfromurllib.parseimporturlparseimportsysfromflaskimportcurrent_app,request,json,redirectfromwerkzeug.exceptionsimportUnauthorized,InternalServerError,HTTPException,BadRequestfromurllib.parseimporturlencodefrommarshmallow.exceptionsimportValidationError# Unauthorized means disconnected# (logged but not allowed to perform an action = Forbidden)@current_app.errorhandler(Unauthorized)
[docs]defhandle_unauthenticated_request(e):ifrequest.accept_mimetypes.best=="application/json":response=e.get_response()response.data=json.dumps({"code":e.code,"name":e.name,"description":e.description,})response.content_type="application/json"returnresponseelse:base_url=current_app.config["URL_APPLICATION"]login_path="/#/login"# FIXME: move in configquery_string=urlencode({"next":request.url})returnredirect(f"{base_url}{login_path}?{query_string}")
[docs]defhandle_internal_server_error(e):# original excepion is set when the InternalServerError have been raised by catched# non-HTTP exception (PROPAGATE_EXCEPTIONS=False, default value when DEBUG=False)original=getattr(e,"original_exception",None)# the original exception may contains sensitive information (e.g. db pwd)# so we return it as description only in debug modeiforiginalandcurrent_app.debug:description=str(original)else:description=e.descriptionresponse=e.get_response()ifrequest.accept_mimetypes.best=="application/json":response.data=json.dumps({"code":e.code,"name":e.name,"description":description,"request_id":request.environ["FLASK_REQUEST_ID"],})returnresponse
@current_app.errorhandler(Exception)
[docs]defhandle_exception(e):ifrequest.accept_mimetypes.best=="application/json":# exceptions are logged by flask when not handled or when re-raised.# as here we construct a json error response, we have to log the exception our-self.current_app.log_exception(sys.exc_info())# TODO: verify that sentry is able to collect these exceptions!server_error=InternalServerError(original_exception=e)returnhandle_internal_server_error(server_error)else:# If PROPAGATE_EXCEPTIONS=True (default value in debug mode),# this will produce a debug page with the full backtrace.# Otherwise, an InternalServerError will be produced by flask.raisee