Flask对请求的处理

时间:2023-03-09 00:47:03
Flask对请求的处理

由http://www.cnblogs.com/steinliber/p/5133386.html 中可得服务器会把environ和start_response发送给Flask的实例app,返回的是app中的wsgi_app

def wsgi_app(self, environ, start_response):

        ctx = self.request_context(environ)
ctx.push()
error = None
try:
try:
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.make_response(self.handle_exception(e))
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error)

在这个函数中,首先创建了请求的上下文并将请求推入请求栈,之后调用full_dispatch_request来得到响应,也就是url对应的视图函数的返回值,full_dispatch_request的程序为

def full_dispatch_request(self):
"""Dispatches the request and on top of that performs request
pre and postprocessing as well as HTTP exception catching and
error handling. .. versionadded:: 0.7
"""
self.try_trigger_before_first_request_functions()
try:
request_started.send(self)
rv = self.preprocess_request()
if rv is None:
rv = self.dispatch_request()
except Exception as e:
rv = self.handle_user_exception(e)
response = self.make_response(rv)
response = self.process_response(response)
request_finished.send(self, response=response)
return response

try_trigger_before_request_function会触发在app中注册的在接受第一个请求前要调用的函数,request_started是信号机制通知请求开始处理,preprocess_request会调用app中注册的请求前函数,若函数的返回值不是None,response的内容就设为该返回值。否则就调用dispatch_request来找到对应的视图函数得到返回值

 def dispatch_request(self):

        req = _request_ctx_stack.top.request
if req.routing_exception is not None:
self.raise_routing_exception(req)
rule = req.url_rule
# if we provide automatic options for this URL and the
# request came with the OPTIONS method, reply automatically
if getattr(rule, 'provide_automatic_options', False) \
and req.method == 'OPTIONS':
return self.make_default_options_response()
# otherwise dispatch to the handler for that endpoint
return self.view_functions[rule.endpoint](**req.view_args)

self.view_functions是通过路由模块产生的endpoint与视图函数相对应的字典。这个就能返回视图函数要返回的值

得到要响应的内容后通过make_response来将其转化为response的对象

    def make_response(self, rv):
"""Converts the return value from a view function to a real
response object that is an instance of :attr:`response_class`. The following types are allowed for `rv`: .. tabularcolumns:: |p{3.5cm}|p{9.5cm}| ======================= ===========================================
:attr:`response_class` the object is returned unchanged
:class:`str` a response object is created with the
string as body
:class:`unicode` a response object is created with the
string encoded to utf-8 as body
a WSGI function the function is called as WSGI application
and buffered as response object
:class:`tuple` A tuple in the form ``(response, status,
headers)`` or ``(response, headers)``
where `response` is any of the
types defined here, `status` is a string
or an integer and `headers` is a list or
a dictionary with header values.
======================= =========================================== :param rv: the return value from the view function .. versionchanged:: 0.9
Previously a tuple was interpreted as the arguments for the
response object.
"""
status_or_headers = headers = None
if isinstance(rv, tuple):
rv, status_or_headers, headers = rv + (None,) * (3 - len(rv)) if rv is None:
raise ValueError('View function did not return a response') if isinstance(status_or_headers, (dict, list)):
headers, status_or_headers = status_or_headers, None if not isinstance(rv, self.response_class):
# When we create a response object directly, we let the constructor
# set the headers and status. We do this because there can be
# some extra logic involved when creating these objects with
# specific values (like default content type selection).
if isinstance(rv, (text_type, bytes, bytearray)):
rv = self.response_class(rv, headers=headers,
status=status_or_headers)
headers = status_or_headers = None
else:
rv = self.response_class.force_type(rv, request.environ) if status_or_headers is not None:
if isinstance(status_or_headers, string_types):
rv.status = status_or_headers
else:
rv.status_code = status_or_headers
if headers:
rv.headers.extend(headers) return rv

make_response可以将字符串,函数,列表等转换成包含状态码以及响应头的response实例,得到response后会调用process_response,他会调用app中注册的after_request_funcs对response进行处理,返回处理过的response,然后full_dispatch_request会发信号通知请求处理结束,返回response,wsgi_app得到response后就返回response(environ,start_response)

 def __call__(self, environ, start_response):
"""Process this response as WSGI application. :param environ: the WSGI environment.
:param start_response: the response callable provided by the WSGI
server.
:return: an application iterator
"""
app_iter, status, headers = self.get_wsgi_response(environ)
start_response(status, headers)
return app_iter

这是response调用时的结果,即返回了可迭代的内容,服务器经过处理将内容发到客户端