如何为 Flask 中的所有 HTTP 错误实现自定义错误处理程序?

How can I implement a custom error handler for all HTTP errors in Flask?

在我的 Flask 应用程序中,我可以通过为每个错误代码添加 errorhandler 装饰器来轻松扩展由单个自定义错误处理程序处理的错误列表,就像

@application.errorhandler(404)
@application.errorhandler(401)
@application.errorhandler(500)
def http_error_handler(error):
    return flask.render_template('error.html', error=error), error.code

但是,这种方法需要为每个错误代码提供一个显式装饰器。有没有办法装饰我的(单个)http_error_handler 函数,以便它处理 所有 HTTP 错误?

您不是唯一一个,一种解决方法是指定您捕获并绑定到 application.error_handler_spec 的 http 错误代码列表,然后删除装饰器,像这样:

def http_error_handler(error):
    return flask.render_template('error.html', error=error), error.code

for error in (401, 404, 500): # or with other http code you consider as error
    application.error_handler_spec[None][error] = http_error_handler

我知道这不理想且丑陋,但它会起作用,我确实希望其他人可以提供更好的解决方案。希望这有帮助。

您可以使用带有异常 class 的 errorhandler 装饰器而不是错误代码作为参数,如 here 所述。因此你可以试试

@application.errorhandler(HTTPException)
def http_error_handler(error):

处理所有 HTTP 错误(大概是指所有 HTTP 错误代码),甚至

@application.errorhandler(Exception)
def http_error_handler(error):

处理所有未捕获的异常

编辑: 查看了烧瓶源代码后,应用程序配置中有一个 'TRAP_HTTP_EXCEPTIONS' 标志,您可以更改它(例如 app.config['TRAP_HTTP_EXCEPTIONS']=True).

(大致)当此标志为 false 时,作为 HTTPException 实例的异常将由您用 errorhandler(n) 修饰的函数处理,其中 n 是 HTTP 错误代码;当此标志为真时,所有 HTTPException 实例都由您用 errorhandler(c) 修饰的函数处理,其中 c 是一个异常 class.

这样

app.config['TRAP_HTTP_EXCEPTIONS']=True

@application.errorhandler(Exception)
def http_error_handler(error):

应该达到你想要的。

因为看起来 HTTPException 对每个 HTTP 错误代码都有 subclasses(见 here),设置 'TRAP_HTTP_EXCEPTIONS' 并用异常 class 装饰你的错误处理程序es not error codes 看起来是一种更灵活的处理方式。

作为参考,我的烧瓶错误处理现在看起来像:

app.config['TRAP_HTTP_EXCEPTIONS']=True

@app.errorhandler(Exception)
def handle_error(e):
    try:
        if e.code < 400:
            return flask.Response.force_type(e, flask.request.environ)
        elif e.code == 404:
            return make_error_page("Page Not Found", "The page you're looking for was not found"), 404
        raise e
    except:
        return make_error_page("Error", "Something went wrong"), 500

这会做我想做的一切,而且似乎可以处理所有错误,包括 HTTP 错误和内部错误。 if e.code < 400 位用于使用 flask 的默认行为进行重定向等(否则最终会出现错误 500,这不是您想要的)

对我来说,以下片段不起作用:

@app.errorhandler(HTTPException)
def _handle_http_exception(e):
    return make_response(render_template("errors/http_exception.html", code=e.code, description=e.description), e.code)

但是将 HTTPException 更改为真实的 NotFound 是可行的。别问我为什么,我没找到答案。

所以我找到了一个非常有效的替代解决方案:

from werkzeug.exceptions import default_exceptions

def _handle_http_exception(e):
    return make_response(render_template("errors/http_exception.html", code=e.code, description=e.description), e.code)

for code in default_exceptions:
    app.errorhandler(code)(_handle_http_exception)

(发现于 Github