目录
- Flask中的Response.
- 一些特殊的响应.
Part1: Flask中的Response
示例程序1
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '***Saltriver***'
if __name__ == '__main__':
app.run()
仍然从Flask.wsgi_app()开始分析. 我们假设整个过程没有异常发生.
def wsgi_app(self, environ, start_response):
...
try:
# 此处获得response.
response = self.full_dispatch_request()
...
# 返回response调用后的结果.
return response(environ, start_response)
...
在full_dispatch_request()中:
def full_dispatch_request(self):
...
if rv is None:
rv = self.dispatch_request()
# 设置print语句,用于查看rv的值.
# 对于示例程序,rv的值为'***Saltriver***'
print('rv--->', rv)
...
response = self.make_response(rv)
response = self.process_response(response)
...
return response
下面我们看self.make_response(rv), make_response文的档说道,rv值可以有4种类型,其中就包括str类型的字符串,其他暂时忽略不管,先分析示例程序中rv为字符串的类型.
def make_response(self, rv):
status_or_headers = headers = None
...
if not isinstance(rv, self.response_class):
# 如果rv为text_type类型.
if isinstance(rv, (text_type, bytes, bytearray)):
# 用response_class对rv进行包装(wrap).
rv = self.response_class(rv, headers=headers,
status=status_or_headers)
headers = status_or_headers = None
...
...
return rv
response_class是如何对rv进行包装的呢?可查看werkzeug官方文档5.4节Response. 文档说, In reality, response objects are nothing more than glorified WSGI applications. 实际上,response对象不过是一个遵循WSGI标准的应用而已. 也就是说,我们甚至可以调用它.调用它时,传入什么参数呢? environ和start_response.
回到full_dispatch_request()中,对于process_response(response),主要做两件事情,调用after_request_functions和设置Cookies, 以此对response做最后的处理.示例程序没有实质性process-response. 最后,返回response(environ, start_response)! 下面来仔细研究研究.
def run(self, host=None, port=None, debug=None, **options):
...
try:
# self为一个Flask实例.
run_simple(host, port, self, **options)
finally:
...
在app.run()里,会调用run_simple函数.我们可以在werkzeug.serving中查看.
def inner():
make_server(hostname, port, application, threaded,
processes, request_handler,
passthrough_errors, ssl_context).serve_forever()
在run_simple()中, 我们会调用make_server(...).serve_forever(), 假设make_server返回的是BaseWSGIServer. 在WSGIRequestHandler中,重点分析run_wsgi()函数.下面看其中的execute函数,因为app(environ, start_response)就在其中执行.
def execute(app):
application_iter = app(environ, start_response)
try:
for data in application_iter:
write(data)
if not headers_sent:
write(b'')
finally:
if hasattr(application_iter, 'close'):
application_iter.close()
application_iter = None
由于我们在Flask.wsgi_app(...)返回一个是一个response对象,传入execute函数的app,也就是response对象.
# Werkzeug/wrappers.py/Class.BaseResponse
def __call__(self, environ, start_response):
app_iter, status, headers = self.get_wsgi_response(environ)
start_response(status, headers)
return app_iter
start_response的任务就是设置了WSGIRequestHandler中run_wsgi中的headers_set变量:
headers_set[:] = [status, response_headers]
而在run_wsgi中的write(data)函数中, 在向wfile写入data之前,会先写入status和response_headers.
def write(data):
assert headers_set, 'write() before start_response'
if not headers_sent: # <---注意此处.
status, response_headers = headers_sent[:] = headers_set
try:
code, msg = status.split(None, 1)
except ValueError:
code, msg = status, ""
self.send_response(int(code), msg) # <---注意此处.
header_keys = set()
for key, value in response_headers:
self.send_header(key, value)
key = key.lower()
header_keys.add(key)
if 'content-length' not in header_keys:
self.close_connection = True
self.send_header('Connection', 'close')
if 'server' not in header_keys:
self.send_header('Server', self.version_string())
if 'date' not in header_keys:
self.send_header('Date', self.date_time_string())
self.end_headers() # <---注意此处.
assert type(data) is bytes, 'applications must write bytes'
self.wfile.write(data) # <---注意此处.
self.wfile.flush()
下面是一些留给我自己思考问题(但还没有解决的问题):
- WSGI接口为什么要这样设计?
- app_iter为什么是iterable的?
... ...
准备再重新读一遍PEP333. _
网友评论