第十四章 应用编程接口(二)

       使用Flask创建REST式WEB服务十分简单。使用熟悉的route()装饰器及其methods可选参数可以声明服务及其所提供资源URL的路由。处理JSON数据同样简单,请求中的JSON数据可以使用request.get_json()转换成字典格式,还可以使用Flask提供的辅助函数jsonify()从Python字典中生成需要包含JSON的响应。

一. 创建API蓝本

       REST式API相关路由是应用中一个自成一体的子集,为了更好地组织代码,我们将这些路由放到独立的蓝本中。API蓝本的基本结构如下:

       如果以后需要创建一个向前兼容的API版本,可以再添加一个带版本号的包,让应用同时支持两个版本的API。api蓝本在api包构造文件中定义: 

from flask import Blueprint

api = Blueprint('api', __name__)

from . import authentication, comments, errors, posts, users

注意:一定要导入蓝本中的所有模块,这样才能注册路由和错误处理程序。因为这些模块同时也要导入蓝本对象以定义路由,所以这些模块都在__init__.py的底部导入,避免出现循环导入。

app/__init__.py:注册API蓝本

...
def create_app(config_name):
    app = Flask(__name__)
    # 使用对象始化app.config
    app.config.from_object(config[config_name])
    config[config_name].init_app(app=app)

    ...

    # 注册API蓝本
    from .api import api as api_blueprint
    app.register_blueprint(api_blueprint, url_prefix='/api/v1')

    return app

       注册api蓝本时指定了一个URL前缀,因此蓝本所有URL都以/api/v1开头。使用域名部署时,我们也会通过subdomain参数指定子域。(例如https://developer.github.com/https://github.com/的一个子域)。

二. 错误处理

       REST式WEB服务将请求的状态告知客户端时,会在响应中发送适当的HTTP状态码,并将额外信息放入响应主体。API返回的常见HTTP状态码如下:

HTTP状态码名称说明
200OK请求成功
201Created创建了一个新资源
202Accepted请求已接收,但仍在处理中,将异步处理
204No Content请求已成功处理,但返回的响应没有数据
400Bad Request请求无效或不一致
401Unauthorized请求未包含身份验证信息,或者提供的凭据无效
403Forbidden禁止访问
404Not Found资源未找到
405Method Not Allowed指定资源不支持请求使用的方法
500Internal Server Error服务器发生错误

       404,405,500错误由Flask自己生成,而且一般会返回HTML响应。这会使客户端很困惑,因为客户端期望所有的响应都是JSON格式。解决办法是“内容协商”。根据HTTP的内容协商机制,在错误处理程序中根据客户端请求格式来改写响应。

app/main/errors.py:使用HTTP内容协商机制处理错误:

from flask import render_template, request, jsonify

from . import main


@main.app_errorhandler(404)
def page_not_found(e):
    if request.accept_mimetypes.accept_json and not request.accept_mimetypes.accept_html:
        response = jsonify({'error': 'not found'})
        response.status_code = 404
        return response
    return render_template('404.html'), 404


@main.app_errorhandler(500)
def internal_server_error(e):
    if request.accept_mimetypes.accept_json and not request.accept_mimetypes.accept_html:
        response = jsonify({'error': 'server error'})
        response.status_code = 500
        return response
    return render_template('500.html'), 500


# 405通常只发生在API中,我们直接返回json响应
@main.app_errorhandler(405)
def method_not_allowed(e):
    response = jsonify(error="The method is not allowed for the requested URL.")
    response.status_code = 405
    return response

       新版的全局错误处理程序检查Accept请求首部(解码为request.accept_mimetypes),根据首部的值决定客户端期望接收的响应格式。仅当客户端接收的响应列表中包含JSON但不包含HTML时,才生成JSON响应。

       其它状态码都由WEB服务生成,可在api蓝本的errors.py模块中以辅助函数的形式实现:

from flask import jsonify
from . import api


def bad_request(message):
    response = jsonify({'error': 'bad request', 'message': message})
    response.status_code = 400
    return response


def unauthorized(message):
    response = jsonify({'error': 'unauthorized', 'message': message})
    response.status_code = 401
    return response


def forbidden(message):
    response = jsonify({'error': 'forbidden', 'message': message})
    response.status_code = 403
    return response

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值