如何自定义Flask的HTTP状态码,例如451

(以下的环境 Flask==0.11.1 Werkzeug==0.11.10)

在 stackoverflow 上看到一个问题,是问如何在 Flask 中用 abort函数触发自定义的错误。abort函数可以触发的错误可以通过字典 default_exceptions 来查看from werkzeug.exceptions import default_exceptions.

首先我们需要自定义一个错误,这个错误类继承于werkzeug.exceptions.HTTPException.我以 451 Unavailable For Legal Reasons 这个状态码为例子。RFC

abort其实是类werkzeug.exceptions.Aborter的实例,abort 初始化的时候就需要 default_exceptions 这个变量,但是我不知道为什么在Aborter.__init__中更新default_exceptions后,在Flask._get_exc_class_and_code中的 default_exceptions 依旧没变。所以我不使用 flask 提供的 abort ,而是先更新 default_exceptions 然后再调用werkzeug.exceptions.Aborter创建一个 abort。

(2016年7月30日更正:
我重新看了一下Aborter.__init__中的代码,之前太不仔细了,self.mapping 并不是直接引用的 default_exceptions, 而是利用 dict 函数生成新的字典。

class Aborter(object):
    def __init__(self, mapping=None, extra=None):
        if mapping is None:
            mapping = default_exceptions
        self.mapping = dict(mapping)
        if extra is not None:
            self.mapping.update(extra)

In [1]: d = {'a':123}
In [2]: c = dict(d)
In [3]: c
Out[3]: {'a': 123}
In [4]: c == d
Out[4]: True
In [5]: id(c) == id(d)
Out[5]: False

from werkzeug.exceptions import HTTPException, default_exceptions,  Aborter
class UnavailableForLegalReasons(HTTPException):
    code = 451
    description = 'BIG BROTHER IS WATCHING YOU'

default_exceptions[451] = UnavailableForLegalReasons
abort = Aborter()  # don't from flask import abort

@app.errorhandler(451)
def uflr(e):
    return e, 451

@app.route('/debug')
def debug():
    abort(451)

然后你可以在浏览器中访问此路径,会得到 HTTP 状态码为 451 的响应了,可是你会发现响应头中的 reason phrase 是 UNKNOWN,你可以自行修改

from werkzeug.http import HTTP_STATUS_CODES
HTTP_STATUS_CODES[451] = 'Unavailable For Legal Reasons'  # or even empty

效果如下

在整个过程中 pycharm 提供了很大的方便,使用 Quick Definition 功能(快捷键为 command+Y)可以很方便的在各种函数变量及对象中转跳,寻找来源,对阅读源码来说非常方便。

我在 stackoverflow 上的回答 Flask - How to create custom abort() code?

参考:

Tag:webflaskStackOverflow Published under (CC) BY-NC-SA