Flask abort() with custom http code

5.6k views Asked by At

I use Flask framework in my project with pure json api. It renders only json responses without html or static files.

I am trying to achieve abort() function with custom http code, in my case 204 (No Content) which isn't defined by default. I have currently code like:

# Error define
class NoContent(HTTPException):
    code = 204
    description = ('No Content')

abort.mapping[204] = NoContent

def make_json_error(ex):
    response = jsonify(error=str(ex))
    response.status_code = (ex.code
                        if isinstance(ex, HTTPException)
                        else 500)
    return response

custom_exceptions = {}
custom_exceptions[NoContent.code] = NoContent

for code in custom_exceptions.iterkeys():
    app.error_handler_spec[None][code] = make_json_error

# Route
@app.route("/results/<name>")
def results(name=None):
    return jsonify(data=results) if results else abort(204)

It works well I get response like:

127.0.0.1 - - [02/Dec/2014 10:51:09] "GET /results/test HTTP/1.1" 204 -

But without any content. It renders nothing, not even blank white page in browser.

I can use errorhandler

@app.errorhandler(204)
def error204(e):
    response = jsonify(data=[])
    return response

But it returns 200 http code. In need 204 here. When I add in error204() line like:

response.status_code = 204

It renders nothing once again.

I am stuck and I have no idea where there is an error with this approach. Please help.

If my approach is wrong from design perspective please propose something else.

Thanks in advance.

2

There are 2 answers

0
Sean Vieira On BEST ANSWER

Remember, HTTP 204 is "No Content". RFC 7231 (and RFC 2616 before it) requires that user-agents ignore everything after the last header line:

The 204 (No Content) status code indicates that the server has successfully fulfilled the request and that there is no additional content to send in the response payload body ... A 204 response is terminated by the first empty line after the header fields because it cannot contain a message body.

~ RFC 7231 (emphasis mine)

The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.

~ RFC 2616

0
davidism On

You need to return the status code in the error handler.

@app.errorhandler(204)
def error204(e):
    response = jsonify(data=[])
    return response, 204

Leaving off the status code is interpreted as 200 by Flask.