在设计API返回内容时,通常需要与前端约定好API返回响应体内容的格式。这样方便前端进行数据反序列化时相应的解析处理,也方便其它服务调用。不同公司有不同的响应内容规范要求,这里以常见的JSON响应体为例:
{
"code": 200,
"data": {
"content": "this is /a/1"
},
"msg": "success"
}
code状态码主要用于表示错误类型区间状态码。如果设计比较简单,可以直接使用HTTP的状态码。如果是一个大型系统,也可以设计一套自定义的状态码。比如:
from enum import Enum
class BizStatus(Enum):
# custom status code
OK = 200
BadRequestA1 = 4001 # 请求参数异常-A情况
BadRequestA2 = 4002 # 请求参数异常-B情况
message 字段是对当前 code 状态码错误明细的补充说明。通常不同的code状态码会有不同的message描述信息。
data 值通常代表返回的响应体内容。
以下代码定义了一个JSON响应类,api在返回的时候需要引用这个响应类。除此之外,还对404和一般异常做了统一处理,当出现这两类异常时,也会返回JSON结构的响应体。
from flask import Flask, request, jsonify, make_response
from http import HTTPStatus
API_KEY_SVCA = "flask_unify_response"
app = Flask(__name__)
class JsonResponse:
"""A class to represent a JSON response."""
def __init__(
self, code: HTTPStatus = HTTPStatus.OK, msg: str = "success", data=None
):
self.code = code
self.msg = msg
self.data = data
def to_dict(self):
return {
"code": self.code.value,
"msg": self.msg,
"data": self.data,
}
def to_json(self):
return jsonify(self.to_dict())
def response(self):
response = make_response(self.to_json(), self.code.value)
response.headers["Content-Type"] = "application/json"
return response
@app.errorhandler(404)
def error_handler_not_found(error):
req_method = request.method
req_path = request.path
return JsonResponse(
code=HTTPStatus.NOT_FOUND,
msg=f"{req_method} {req_path} Not Found",
).response()
@app.errorhandler(Exception)
def error_handler_generic(error):
req_method = request.method
req_path = request.path
return JsonResponse(
code=HTTPStatus.INTERNAL_SERVER_ERROR,
msg=f"Internal Server Error. {req_method} {req_path}",
data={"error": str(error)},
).response()
@app.get("/a/1")
def apitest_a1():
return JsonResponse(
code=HTTPStatus.OK, msg="success", data={"content": "this is /a/1"}
).response()
@app.get("/a/2")
def apitest_a2():
raise Exception("exception in a/2")
if __name__ == "__main__":
app.run(host="127.0.0.1", port=8001)
客户端请求测试:
$ curl -s http://127.0.0.1:8001/a/1 | python3 -m json.tool
{
"code": 200,
"data": {
"content": "this is /a/1"
},
"msg": "success"
}
$ curl -s http://127.0.0.1:8001/a/2 | python3 -m json.tool
{
"code": 500,
"data": {
"error": "exception in a/2"
},
"msg": "Internal Server Error. GET /a/2"
}
$ curl -s http://127.0.0.1:8001/a/3 | python3 -m json.tool
{
"code": 404,
"data": null,
"msg": "GET /a/3 Not Found"
}