1

In the Flask-restful documentation on custom error handlers it says:

Flask-RESTful will call the handle_error() function on any 400 or 500 error that happens on a Flask-RESTful route, and leave other routes alone. You may want your app to return an error message with the correct media type on 404 Not Found errors; in which case, use the catch_all_404s parameter of the Api constructor.

My simplified setup for an API with blueprint:

from flask import Blueprint
from flask_restful import Api
from .resources.tool import ToolDetail, Tools

api_bp = Blueprint('api', __name__, subdomain='<hostname>', url_prefix='/api')
api = Api(api_bp, catch_all_404s=True)

api.add_resource(Tools, '/tools', '/tools/<int:page>', '/tools/<int:page>/<int:per_page>')
api.add_resource(ToolDetail, '/tool/<int:id>')

With catch_all_404s=True any 404 results in a response like:

{
  "message": "The requested URL was not found on the server.  If you entered the URL manually please check your spelling and try again."
}

Also for requests on other blueprints! I would expect the catch_all_404s=True to have an effect on the defined blueprint only.

Removing the catch_all_404s=True from the snippet above the handle_error() function is never called. Also not for requests with the /api path.

So my question is: how to make flask-restful catch all 404s within the blueprint, but not outside it (i.e. not in other blueprints).

Edit: as pointed out in the comment below, this catch_all behavior not being limited to the blueprint is caused by a limitation in Flask itself. Still remaining problem: with catch_all_404s=False, 404s are never caught by flask-restful, even within the routes, e.g. http://somehost.domain.com/api/tools/x is caught by the error handler of the app, not the error handler of flask-restful.

pors
  • 3,856
  • 36
  • 33
  • Possible duplicate of [flask: error\_handler for blueprints](http://stackoverflow.com/questions/12768825/flask-error-handler-for-blueprints) – danidee Nov 09 '16 at 19:01
  • @danidee well yes it is related, but only half the picture. It does explain why catch_all_404s=True applies to the whole app, and not just the blueprint. Thanks for pointing to that! But setting it to False results in 404s never being caught by flask-restful. I'll update the question. – pors Nov 10 '16 at 11:35

1 Answers1

0

The Api class in flask-restful handles the errors. If you want the errors to be handled at the app level, have the error handler reraise the error in the custom class with the handle_error method. You can also handle custom errors specific to blueprints in the same method. Custom Class(ExtendApi) extends base class Api

class ExtendApi(Api):
    """This class overrides 'handle_error' method of 'Api' class ,
    to extend global exception handing functionality of 'flask-restful'.
    """

    def handle_error(self, e):
        # reraise the error so that it is handled in the app level error handlers
        # Add custom handlers below if required
        if getattr(e, "code"):
            if e.code == 404:
               return {"message": "My custom message"}, 404
        raise e

Use custom class instead of Api from flask-restful

my_blueprint = Blueprint("my_blueprint", __name__)

blueprint_api = ExtendApi(my_blueprint)
TC Arlen
  • 1,442
  • 2
  • 11
  • 19