0

I want to define custom error handling for a Flask-restful API

The flask custom error(FlaskGenericException) is raised but is not handled by restplus errorhandler. it just throws a 500 Internal Server error.

Not sure why the dict defined inside exceptions.py is not thrown as api response.

Expected Result

{'user': 'Lionel Messi', 'company': 'Soccer Brazil','message': 'A generic error'}

Here are my files that I am using to test this:

app.py

import json,os
import logging
import sys
import requests
import config
from os import environ
from flask import Flask, request, jsonify, Response
from flask_jwt_extended import (JWTManager, jwt_required)
from flask_restplus import Api, Resource, reqparse, fields, inputs
from cal_Test import calTest
from exceptions import FlaskGenericException




# Setup Flask Server
app = Flask(__name__,root_path=os.path.join(os.getcwd(), './'))


app.config.from_object(config.Config)
api = Api(app=app,
          version='0.1',
          title="Test Cal API",
          doc="/swagger/",
          description='TestCal = Cal Test')
ns = api.namespace('/', description='Cal Test Api')

@api.errorhandler(FlaskGenericException)
def handle_error(error):
    response = jsonify(error.to_dict())
    response.status_code = error.status_code
    return response


resource_parser = reqparse.RequestParser()
resource_parser.add_argument('test', type=str, required=True)


resource_flds = api.model('Resource', {
    'test': fields.String(required = True),
})

@ns.route('/test', methods=['POST'])
class TestCal(Resource):


    # @jwt_required
    @ns.doc(body=resource_flds)
    @ns.expect(resource_flds, validate=True)
    def post(self):
        request_data = resource_parser.parse_args()
        caltst = calTest()
        result = caltst.cal_test(request_data)
        response = app.response_class(
        response=json.dumps(result),
        status=200,
        mimetype='application/json'
    )
        return response


if __name__ == "__main__":
    app.run(debug=True)

cal_Test.py

import pandas as pd
import pyodbc
import scipy.stats as st
import numpy as np
import pandas as pd
from scipy.stats import norm
from flask import Flask, request, jsonify
import os
from exceptions import FlaskGenericException




class calTest:

def __init__(self):
    self.test_name = 'Hi! I am test'



def cal_test(self,reqdata):
    if self.test_name == reqdata['test']:
        return "Successfull"
    else:
        raise FlaskGenericException('A generic error', status_code=404, payload={'user': 'Lionel Messi', 'company': 'Soccer Brazil'})

exceptions.py

class FlaskGenericException(Exception):
    status_code = 500   # default unless overridden
    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
min2bro
  • 554
  • 2
  • 9
  • 19
  • This is an existing bug in flask-restplus: https://github.com/noirbizarre/flask-restplus/issues/744 and will be fixed in 0.14.0 release. No release date yet. – min2bro May 18 '20 at 17:14

1 Answers1

0

Ran into the same issue, I ended up using the abort method from Flask. I don't know if it fits your use case, but give it a try.

from flask import abort 

def cal_test(self,reqdata):
    if self.test_name == reqdata['test']:
        return "Successfull"
    else:
        abort(404, "A generic error")