下面的是一个Flask框架,可以按照此图对源码进行解读:
WSGI端口:
①浏览器发送一个HTTP请求;
②服务器收到请求,生成一个HTML文档;
③把HTML文档作为HTTP响应的Body发送给浏览器;
④器收到HTTP响应,从HTTP Body取出HTML文档并显示。
最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。
如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。
正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。
这个接口就是WSGI:Web Server Gateway Interface。
1.路由规则的构建:
a.通过 @app.route()
b.通过 app.add_url_rule
(1) rule:url 规则字符串,可以是静态的" /path",也可以包含" /"
(2) endpoint:要注册规则的"endpoint",默认是 "view_func "的名字
(3) view_func:相对应 url 的处理函数,也被称为视图函数
出现的代码只有说明的一部分
@app.route('/')
def hello():
return ''hello,world ! ''
进行函数封装之后
def hello():
return "helo world ! "
app.add_url_rule('/', 'hello', hello)
2.route方法
def route(self, rule, **options):
def decorator(f):
endpoint = options.pop("endpoint", None)
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
3.验证路由规则构建的两种方法
def add_url_rule(
self,
rule,
endpoint=None,
view_func=None,
provide_automatic_options=None,
**options
):
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func)
options["endpoint"] = endpoint
methods = options.pop("methods", None)
4.视图函数的注册:
在上一步中if endpoint is None:判断endpoint是空,endpoint = _endpoint_from_view_func(view_func),options[“endpoint”] = endpoint将endpoint添加到字典,从下面代码中可以看出函数返回值为name属性
def _endpoint_from_view_func(view_func):
assert view_func is not None, "expected view func if endpoint is not provided."
return view_func.__name__
5.method
if methods is None:
methods = getattr(view_func, "methods", None) or ("GET",) #提取属性,初始属性为"GET"
if provide_automatic_options is None:
if "OPTIONS" not in methods:
provide_automatic_options = True
required_methods.add("OPTIONS")
else:
provide_automatic_options = False
methods |= required_methods #连接字典结果放在methods中
6.映射关系
routing.py的Rule类建立了(url,endpoint,methods)的映射关系
rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options
self.url_map.add(rule)
7.rule对象的存储
url_map = Map([
Rule('/',endpoint=/index/),
Rule('static',endpoint='static'
])
8.map()函数和视图函数(view_func)更新
if view_func is not None:
old_func = self.view_functions.get(endpoint)
if old_func is not None and old_func != view_func:
raise AssertionError(
"View function mapping is overwriting an "
"existing endpoint function: %s" % endpoint
)
self.view_functions[endpoint] = view_func