当前位置:网站首页>Flask1.1.4 werkzeug1.0.1 source code analysis: Routing
Flask1.1.4 werkzeug1.0.1 source code analysis: Routing
2022-07-07 20:23:00 【An engineer$】
Routing is roughly divided into two parts :
- Routing binding : take url_rule and view_func Bound to the falsk In the example , This is in the previous article Start process I've already talked about it in
- Route resolution : When the actual request comes , according to environ To match to the corresponding Rule, And from environ The parameters are resolved from , And then according to Rule.endpoint Go to view_functions Find the corresponding view_function To call
This article focuses on the second part ,Flask The route matching of is actually based on werkzeug.routing.Map and werkzeug.routing.Rule
We can write a simple demo, Learn how to use these two tools .
# structure map
url_map = Map([Rule("/a", endpoint='a'), Rule("/b", endpoint='b'), Rule("/c/<path_param>", endpoint='c')])
# call Map.bind() return MapAdapter object
urls = url_map.bind('eee.com', '/')
# MapAdapter.match() Make request matching
print(urls.match("/a"))
print(urls.match("/c/123"))
print(urls.match("/dd"))
give the result as follows :
# When matched, it will return (endpoint, view_func_args)
('a', {
})
('c', {
'path_param': '123'})
# It doesn't match Throw exceptions
Traceback (most recent call last):
File "/Users/panc/Documents/projects/PycharmProjects/grpc-client/pycode/flask_demo.py", line 9, in <module>
print(urls.match("/dd"))
File "/usr/local/Caskroom/miniconda/base/envs/python37/lib/python3.7/site-packages/werkzeug/routing.py", line 1945, in match
raise NotFound()
werkzeug.exceptions.NotFound: 404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
ok, Now let's start to study Flask The routing process of ~
First of all, pay attention ,Flask There is no direct URL and view_func Connect , Instead, it adds endpoint The concept of . In fact, it's easy to understand ,URL Most of the time, it is not fixed , It also includes the parameter part , Not suitable for key. in addition , From the steps of processing the request , First, according to the request url Information to match the registered url_rule, And then find the corresponding view_func Perform logical . This is divided into two steps , take url Information and view_func Separate storage , And then through endpoint It seems appropriate to connect the two .
Start process It has been said in an article ,HTTP Format data to WSGI After formatting data , call flask_app(environ, start_response) Execute specific processing logic
class Flask(_PackageBoundObject):
def __call__(self, environ, start_response):
return self.wsgi_app(environ, start_response)
def wsgi_app(self, environ, start_response):
# Here we build flask.ctx.RequestContext object
# The build process includes Routing processing logic
ctx = self.request_context(environ)
error = None
try:
try:
# Routing logic is also included here Stack the current request context
# The purpose of stack entry is to pass some information to the following by non parameter transfer view_function
ctx.push()
# RequestContext Object construction and push The routing logic has been handled in the process of
# After that, you only need to get the currently requested RequestContext example , use endpoint Just get and call the method
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.handle_exception(e)
except: # noqa: B001
error = sys.exc_info()[1]
raise
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
# Clean up the current context after the request processing Out of the stack
ctx.auto_pop(error)
def request_context(self, environ):
# Notice that the first parameter is flask example
return RequestContext(self, environ)
def create_url_adapter(self, request):
if request is not None:
subdomain = (
(self.url_map.default_subdomain or None)
if not self.subdomain_matching
else None
)
# Previous demo I've seen this inside bind_to_environ and bind It's the same thing
# Return to one MapAdapter object
return self.url_map.bind_to_environ(
request.environ,
server_name=self.config["SERVER_NAME"],
subdomain=subdomain,
)
def full_dispatch_request(self):
self.try_trigger_before_first_request_functions()
try:
request_started.send(self)
rv = self.preprocess_request()
if rv is None:
# Perform the requested
rv = self.dispatch_request()
except Exception as e:
rv = self.handle_user_exception(e)
# Here will be view_function Return Convert to Response object
return self.finalize_request(rv)
def dispatch_request(self):
# Take out the current RequestContext object And get it request attribute
req = _request_ctx_stack.top.request
# Route matching failed Throw exceptions
if req.routing_exception is not None:
self.raise_routing_exception(req)
rule = req.url_rule
# Final Rule Object's endpoint To find the corresponding view_function And call... With parameters Execute specific logic
return self.view_functions[rule.endpoint](**req.view_args)
Now let's look at the key of routing RequestContext
class RequestContext(object):
def __init__(self, app, environ, request=None, session=None):
# Saved here flask app example
self.app = app
if request is None:
# Use environ Construct a Request object
request = app.request_class(environ)
self.request = request
self.url_adapter = None
try:
# here Is to Map.bind Got a MapAdapter object
self.url_adapter = app.create_url_adapter(self.request)
except HTTPException as e:
self.request.routing_exception = e
self.flashes = None
self.session = session
def match_request(self):
try:
# In fact, that is MapAdapter.match() There is no reference here because it was Map.bind_to_environ()
result = self.url_adapter.match(return_rule=True)
# unpacking url_rule namely Rule Object contains endpoint Information view_args The parameter
# in other words RequestContext object push() when , The route resolution process has been completed
# Bind the parsing result to RequestContext Object's request Attribute
self.request.url_rule, self.request.view_args = result
except HTTPException as e:
self.request.routing_exception = e
def push(self):
"""Binds the request context to the current context."""
# Stack the current request context object Convenient for subsequent delivery
_request_ctx_stack.push(self)
if self.url_adapter is not None:
# The key
self.match_request()
ok, At this point, the route parsing process is over ~
To sum up :
- The core of the core is still werkzeug Of Map、Rule、MapAdapter object
- The binding of route is flask_app.add_url_rule() There are many ways , It can be app.route() Or use blueprint, But the essence is flask_app.add_url_rule()
- Route resolution , Nature is map_adapter = url_map.bind_to_environ() -> rule, view_args = map_adapter.match() -> view_functions[rule.endpoint] (**view_args)
- among url_map.bind_to_environ() stay structure RequestContext Object , match Operation in RequestContext.push() When the . After the context object is ready to be merged into the stack , Just take out the current request context object , And then use endpoint To find the corresponding view_func And execute it .
边栏推荐
- ASP. Net learning & ASP's one word
- 让这个CRMEB单商户微信商城系统火起来,太好用了!
- Vulnhub's funfox2
- 数据孤岛是企业数字化转型遇到的第一道险关
- Creation of kubernetes mysql8
- 《数字图像处理原理与实践(MATLAB版)》一书之代码Part2[通俗易懂]
- 有用的win11小技巧
- [auto.js] automatic script
- 力扣 1790. 仅执行一次字符串交换能否使两个字符串相等
- [award publicity] issue 22 publicity of the award list in June 2022: Community star selection | Newcomer Award | blog synchronization | recommendation Award
猜你喜欢
让这个CRMEB单商户微信商城系统火起来,太好用了!
One click deployment of any version of redis
网络原理(1)——基础原理概述
复杂因子计算优化案例:深度不平衡、买卖压力指标、波动率计算
AADL Inspector 故障树安全分析模块
Implement secondary index with Gaussian redis
机器学习笔记 - 使用Streamlit探索对象检测数据集
With st7008, the Bluetooth test is completely grasped
php 获取图片信息的方法
PHP method of obtaining image information
随机推荐
第二十章 使用工作队列管理器(三)
JVM GC garbage collection brief
PHP method of obtaining image information
力扣 1790. 仅执行一次字符串交换能否使两个字符串相等
如何满足医疗设备对安全性和保密性的双重需求?
Vulnhub's funfox2
Micro service remote debug, nocalhost + rainbow micro service development second bullet
The boundary of Bi: what is bi not suitable for? Master data, Martech? How to expand?
Mrs offline data analysis: process OBS data through Flink job
数据孤岛是企业数字化转型遇到的第一道险关
力扣 989. 数组形式的整数加法
Flask1.1.4 Werkzeug1.0.1 源码分析:路由
基于深度学习的目标检测的更新迭代总结(持续更新ing)
[philosophy and practice] the way of program design
[award publicity] issue 22 publicity of the award list in June 2022: Community star selection | Newcomer Award | blog synchronization | recommendation Award
Nebula importer data import practice
Network principle (1) - overview of basic principles
[auto.js] automatic script
解决/bin/sh进去的容器运行可执行文件报not found的问题
ISO 26262 - 基于需求测试以外的考虑因素