一、前言
之前陆陆续续看过一点flask源码但不是很系统。最近计划把之前的笔记串起来,算是作为自己的积累。
为什么选择flask?答案比较简单:
- 代码量不是很大,核心部分也就万行左右
- 代码相对规范
- 注释很详细
flask 源码:https://github.com/pallets/flask
flask 文档:http://flask.pocoo.org/
falsk开发团队:https://www.palletsprojects.com
版本:1.1.dev
二、正文
1.wsgi的概念
全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。(其他语言不怎么提这个概念)
在flask框架中,wsgi负责连接server和我们APP里面的逻辑,完成整个HTTP请求的处理和响应。
2.编写一个demo app
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
启动我们的app后,即可访问到我们编写的逻辑(”Hello, World!”)了。当然一个HTTP请求是怎么到达我们函数,以及我们函数是怎么处理这块逻辑并将其返回,这个就是本文的重点。
3.request与response处理逻辑
- app启动,Flask的call函数启动wsgi_app
def __call__(self, environ, start_response):
"""The WSGI server calls the Flask application object as the
WSGI application. This calls :meth:`wsgi_app` which can be
wrapped to applying middleware."""
return self.wsgi_app(environ, start_response)
- 如图所示的,整个过程正常情况下涉及:wsgi_app、full_dispatch_request、preprocess_request、dispatch_request、finalize_request、make_response、process_response
函数说明:
- wsgi_app:生成request对象以及上下文环境。
def wsgi_app(self, environ, start_response):
"""The actual WSGI application. This is not implemented in
:meth:`__call__` so that middlewares can be applied without
losing a reference to the app object. Instead of doing this::
app = MyMiddleware(app)
It's a better idea to do this instead::
app.wsgi_app = MyMiddleware(app.wsgi_app)
Then you still have the original application object around and
can continue to call methods on it.
.. versionchanged:: 0.7
Teardown events for the request and app contexts are called
even if an unhandled error occurs. Other events may not be
called depending on when an error occurs during dispatch.
# 省略部分注释
"""
ctx = self.request_context(environ)
error = None
try:
try:
ctx.push()
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.handle_exception(e)
except:
error = sys.exc_info()[1]
raise
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error)
- full_dispatch_request:主要用途:启动trigger,发送开始处理的signal,启动preprocess_request和finalize_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)
return self.finalize_request(rv)
- preprocess_request:主要call before_request_funcs
- dispatch_request:开始调度request的处理,主要包括:匹配url规则、运行view_functions(用户自定义的函数)
def dispatch_request(self):
"""Does the request dispatching. Matches the URL and returns the
return value of the view or error handler. This does not have to
be a response object. In order to convert the return value to a
proper response object, call :func:`make_response`.
.. versionchanged:: 0.7
This no longer does the exception handling, this code was
moved to the new :meth:`full_dispatch_request`.
"""
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)
finalize_request: 主要是call make_response,然后发送结束request的signal
官方注释:Given the return value from a view function this finalizes the request by converting it into a response and invoking the postprocessing functions. This is invoked for both normal request dispatching as well as error handlers.make_response:将view_function的返回值转换为response_class
最后通过response对象将结果返还给server。
参考文章:
https://blog.csdn.net/bestallen/article/details/54342120