Flask 在请求出现异常时一般会抛出 HTTPException,他会把异常信息以页面的形式展示,这对一个API项目来说是多余的,我们可以通过继承 HTTPException 返回自己想要的结构。
比如一般请求中需要用 data、msg、msg_code 这些字段。并且规划好不同的 msg_code 代表了什么信息。
{
data: null,
msg: "Token不合法",
msg_code: 10010
}
通过覆写 HTTPException 的 get_body()、get_headers(),使其返回 JSON 结构。
在 HTTP 状态码的返回上,不同的项目会有不同的选择,如果追求 RESTful 风格的返回,也就是比如在资源找不到时必须返回 404,创建资源成功返回 201 等,这样严格按照规范来做的话需要在配置中把 RESTFUL_HTTP_CODE 设置为 True。
默认 RESTFUL_HTTP_CODE 是关闭的,因为在很多时候这个规范也并非强制的,状态码返回200 更便于前端操作。
class APIException(HTTPException):
code = 500
msg_code = 9999
data = None
msg = '服务器未知错误'
headers = {'Content-Type': 'application/json'}
def __init__(self, data=None, code=None, msg_code=None, msg=None, headers=None):
if data:
self.data = data
if msg_code:
self.msg_code = msg_code
if msg:
self.msg = msg
if headers:
self.headers = headers
# 状态码返回风格
if current_app.config['RESTFUL_HTTP_CODE']:
if code:
self.code = code
else:
self.code = 200
super(APIException, self).__init__()
def get_body(self, environ=None):
body = dict(
msg_code=self.msg_code,
msg=self.msg,
data=self.data
)
return json.dumps(body)
def get_headers(self, environ=None):
return [(k, v) for k, v in self.headers.items()]
# --- 成功 0~999 ---
class Success(APIException):
code = 200
msg_code = 0
msg = '成功'
class Created(APIException):
code = 201
msg_code = 1
msg = '创建成功'
class Updated(APIException):
code = 201
msg_code = 2
msg = '更新成功'
class Deleted(APIException):
code = 202
msg_code = 3
msg = '删除成功'
Flask 可以捕获全局异常,我们将异常都以 APIException 的形式抛出,在开发环境下未知的异常任然以堆栈形式抛出,以方便调试。
def register_exception(app):
@app.errorhandler(Exception)
def handle_error(e):
if isinstance(e, APIException):
return e
elif isinstance(e, HTTPException):
return APIException(code=e.code, msg=e.name)
else:
if not app.config['DEBUG']:
return ServerError()
raise e