客户端发送过来请求之后,首先会携带参数调用app对象__call__()的方法,该方法中只完成了一件事,就是调用wsgi_app()
方法
def __call__(self, environ, start_response):
/*
@environ : 创建的WSGI环境
@start_response : 接受状态码的响应对象
*/
return self.wsgi_app(environ, start_response)
进入到wsgi_app()
方法的源码中,可以得知wsgi_app()
方法的重要信,该函数类似于CPU完成着对整个框架请求得调度。
def wsgi_app(self, environ, start_response):
with self.request_context(environ):
rv = self.preprocess_request()
if rv is None :
rv = self.dispatch_request()
response = self.make_response(rv)
response = self.process_response(response)
return response(environ, start_response)
request_context(environ)
函数源码刨析 :
通过进入request_context(environ)
函数可以看出request_context(environ)
其实是实现了上下文管理器得包装类,该上下文管理器在请求进入之前被创建,在该管理器中有一点相当重要:就是__enter__中得 _request_ctx_stack.push(self)
,不难理解该方法可以使得请求在进入时被创建,之后被推送到_request_ctx_stack
,在请求结束时会被相应的移除。
def request_context(self, environ) :
return _RequestContext(self, environ)
class _RequestContext(object):
def __init__(self, app, environ) :
self.app = app
#为WSGI环境创建Url适配器
self.url_adapter = app.url_map.bind_to_environ(environ)
#为SWGI环境创建请求对象
self.request = app.request_class(environ)
self.session = app.open_session(self.request)
self.g = _RequestGlobals()
self.flashes = None
def __enter__(self):
_request_ctx_stack.push(self)
def __exit__(self, exc_type, exc_value, tb):
# 在调试模式(debug mode)而且有异常发生时,不要移除(pop)请求堆栈。
# 这将允许调试器(debugger)在交互式shell中仍然可以获取请求对象。
if tb is None or not self.app.debug:
_request_ctx_stack.pop()
上下文管理器被创建完成之后,系统会调用preprocess_request()
方法从before_request_funcs
中逐一遍历获取访问对象,那么before_request_funcs
中到底放的是什么 ?官方给出得解释是在请求被分发前需要调用得函数,其中存放得请求转发之前存放函数【端点函数】。
def preprocess_request(self) :
for func in self.before_request_funcs:
rv = func()
if rv is not None:
return rv
在实际的请求分发之前调用,而且将会逐一调用before_request_funcs
中函数。如果其中某一个函数返回一个值,这个值将会作为视图返回值,处理并停止进一步的请求处理。
如果调用preprocess_request
函数没有函数值,那么就会执行请求分发得操作,请求分发的方法封装在dispatch_request()
:
def dispatch_request(self):
try:
#匹配成功,返回视图函数
endpoint, values = self.match_request()
return self.view_functions[endpoint](**values)
except HTTPException as e:
handler = self.error_handlers.get(e.code)
if handler is None:
return e
return handler(e)
except Exception as e:
handler = self.error_handlers.get(500)
if self.debug or handler is None:
raise
return handler(e)
def match_request(self):
rv = _request_ctx_stack.top.url_adapter.match()
request.endpoint, request.view_args = rv
return rv
请求转发的流程 :在_request_ctx_stack
中通过适配器利用url映射匹配视图函数,这种情况下会出现两种可能,一种是匹配成功一种是匹配异常,对于前一种情况,会通过view_functions
映射表,将视图函数组装完成直接返回,如果匹配失败,难免查询异常处理器将结果返回。到这里并没有结束,有时候,返回的结果中,返回值并非真正响应的对象,所以需要将返回值分装称为一个真正得响应对象,make_response
就提供了这种便利
/*
@response_class :这个对象将被直接返回
@str :使用这个字符串作为主体创建一个请求对象
@unicode :将这个字符串进行utf-8编码后作为主体创建一个请求对象
@tuple :使用这个元组的内容作为参数创建一个请求对象
@a WSGI function : 这个函数将作为WSGI程序调用并缓存为响应对象
*/
def make_response(self, rv):
if isinstance(rv, self.response_class):
return rv
if isinstance(rv, string):
return self.response_class(rv)
if isinstance(rv, tuple):
return self.response_class(*rv)
return self.response_class.force_type(rv,request.environ)
返回响应对象之前,需要对响应得对象进行再次加工,或者在响应之前执行其他操作process_response
中提供了将session于响应对象绑定的实例以及调用请求转发完成之后需要执行的操作,有时候需要对其进行其他操作的处理,那么可以重写该方法。
session = _request_ctx_stack.top.session
if session is not None:
self.save_session(session, response)
for handler in self.after_request_funcs :
response = handler(response)
return response
至此一个完成的请求的过程基本完成。