隐式响应:
1. 视图函数的返回值会被隐式转换为一个响应对象
2. 如果返回的是一个合法的响应对象,则会从视图函数中直接返回
3. 如果返回的是一个字符串,会用字符串数据和默认参数创建字符串为主体,状态码为200,MIME类型为text/html的werkzeug.wrappers.Response响应对象
4. 如果返回的是一个元组(response, status, headers),且至少包含一个元素,status值会覆盖状态代码,headers可以是一个列表或是字典,作为额外的消息头
5. 如果上述条件均不满足,Flask会通过werkzeug.wrappers.Response.force_type(rv, request.environ)强制返回
#!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # 51CTOBG: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 from flask import Flask, render_template, make_response # 说明: 导入其它模块 app = Flask(__name__) @app.errorhandler(404) def not_found(error): return render_template('errors/404.html'), 404
显式响应:
说明: 显式响应就是通过flask.make_response来创建响应对象,它接收三个参数,response, status, headers然后返回响应对象,可以通过调用rsp.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)和rsp.delete_cookie(key, path='/', domain=None)来设置或删除cookie,还可以通过添加额外头部信息返回
#!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # 51CTOBG: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 from flask import Flask, render_template, make_response # 说明: 导入其它模块 app = Flask(__name__) @app.errorhandler(404) def server_err(error): return make_response(render_template('errors/404.html'), 500) if __name__ == '__main__': app.run(host='0.0.0.0', port=9000, debug=True)
说明: 其实更加推荐使用make_response显式响应,因为其可以返回一个响应对象,可以通过响应对象做很多事情,如设置浏览器客户端cookie等
自定响应:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # 51CTOBG: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 import json from flask import Flask, request, make_response from werkzeug.wrappers import Response # 说明: 导入其它模块 class JSONPResponse(Response): @classmethod def force_type(cls, response, environ=None): if isinstance(response, dict): response = '{0}({1})'.format(response.get('callback'), json.dumps(response.get('data'))) response = make_response(response) return super(JSONPResponse, cls).force_type(response, environ) app = Flask(__name__) app.response_class = JSONPResponse @app.route('/api/hosts/jsonp') def jsonp(): rm_hosts = ['192.168.1.1', '192.168.1.2', '192.168.1.3', '192.168.1.4', '192.168.1.5', '192.168.1.6'] callback = request.args.get('callback') return {'callback': callback, 'data': rm_hosts} if __name__ == '__main__': app.run(host='0.0.0.0', port=9000, debug=True)
JSONP
说明: 如上通过自定义响应实现了一个JSNP跨域,需要注意的是继承自Response类时只需要重写一个BaseResponse基类的force_type类方法,force_type接收两个参数,一个是视图函数返回的原始数据,一个是请求对象信息,如果为空默认使用的是request.environ,但是需要注意由于我们自定义的字典式响应并不满足默认响应条件,所以会自动调用Response.force_type(response, request.environ)来转换为一个请求对象,所以上面我们使用使用了make_response(response)直接生成了一个响应对象传递给基类的.force_type方法来生成响应
http GET http://127.0.0.1:9000/api/hosts/jsonp callback==hostsCallback HTTP/1.0 200 OK Content-Length: 105 Content-Type: text/plain; charset=utf-8 Date: Thu, 27 Oct 2016 03:09:32 GMT Server: Werkzeug/0.11.11 Python/2.7.11 hostsCallback(["192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.4", "192.168.1.5", "192.168.1.6"])