how to get access to error message from abort command when using custom error handler
Asked Answered
S

4

63

Using a python flask server, I want to be able to throw an http error response with the abort command and use a custom response string and a custom message in the body

@app.errorhandler(400)
def custom400(error):
    response = jsonify({'message': error.message})
    response.status_code = 404
    response.status = 'error.Bad Request'
    return response

abort(400,'{"message":"custom error message to appear in body"}')

But the error.message variable comes up as an empty string. I can't seem to find documentation on how to get access to the second variable of the abort function with a custom error handler

Sexpot answered 22/1, 2014 at 21:59 Comment(1)
Is error.description what you're looking for?Saturant
F
102

If you look at flask/__init__.py you will see that abort is actually imported from werkzeug.exceptions. Looking at the Aborter class, we can see that when called with a numeric code, the particular HTTPException subclass is looked up and called with all of the arguments provided to the Aborter instance. Looking at HTTPException, paying particular attention to lines 85-89 we can see that the second argument passed to HTTPException.__init__ is stored in the description property, as @dirn pointed out.

You can either access the message from the description property:

@app.errorhandler(400)
def custom400(error):
    response = jsonify({'message': error.description['message']})
    # etc.

abort(400, {'message': 'custom error message to appear in body'})

or just pass the description in by itself:

@app.errorhandler(400)
def custom400(error):
    response = jsonify({'message': error.description})
    # etc.

abort(400, 'custom error message to appear in body')
Focalize answered 23/1, 2014 at 6:46 Comment(3)
This is a great way to extend abort's functionality with custom error messages. Thank you for thisDevoir
Is there a way to do this with every status code instead of having to write a custom error handler for each code? Ex: abort(409, 'There was a time conflict'), abort(400, 'custom error message to appear in body')Enthusiasm
Duplicate answer - https://mcmap.net/q/64822/-sending-json-and-status-code-with-a-flask-response-duplicateSinglecross
D
75

People rely on abort() too much. The truth is that there are much better ways to handle errors.

For example, you can write this helper function:

def bad_request(message):
    response = jsonify({'message': message})
    response.status_code = 400
    return response

Then from your view function you can return an error with:

@app.route('/')
def index():
    if error_condition:
        return bad_request('message that appears in body')

If the error occurs deeper in your call stack in a place where returning a response isn't possible then you can use a custom exception. For example:

class BadRequestError(ValueError):
    pass

@app.errorhandler(BadRequestError)
def bad_request_handler(error):
    return bad_request(str(error))

Then in the function that needs to issue the error you just raise the exception:

def some_function():
    if error_condition:
        raise BadRequestError('message that appears in the body')

I hope this helps.

Damick answered 23/1, 2014 at 1:30 Comment(3)
is it preferable (faster) to return bad_request(...) directly when you can rather than just raise BadRequestError(...) ?Hussy
You can raise abort anywhere when you want, no need to return.Refraction
How is this any better? When not done from a view (and you need to register the error handler), the only difference is that you call raise BadRequestError instead of abort, with the added complication of having to register a custom exception.Faint
A
43

I simply do it like this:

    abort(400, description="Required parameter is missing")
Ashleyashli answered 25/10, 2017 at 11:33 Comment(4)
The best answer in my opinion.Empale
When you want to return a json type response. You need make_response.Refraction
To clarify Minh's comment from Jul 7, in Werkzeug>=1.0.1 the code in this answer will generate a proper JSON response. I was even able to pass a dict as description and Werkzeug correctly generated a nested JSON response.Nievelt
Unfortunately this returns HTML I do not want. I just want the message to print ONLY. Here is what curl output looks like: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <title>403 Forbidden</title> <h1>Forbidden</h1> <p>Required parameter is missing</p>Evocative
B
10

flask.abort also accepts flask.Response

abort(make_response(jsonify(message="Error message"), 400))
Barbarous answered 16/8, 2018 at 15:13 Comment(1)
You even not need to using jsonify: abort(make_response({'message': 'Error message'}, 400))Refraction

© 2022 - 2024 — McMap. All rights reserved.