当前位置:网站首页>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 .
边栏推荐
- Force buckle 599 Minimum index sum of two lists
- Oracle 存儲過程之遍曆
- Prometheus remote_write InfluxDB,unable to parse authentication credentials,authorization failed
- Get webkitformboundary post login
- [MySQL - Basic] transactions
- 解决/bin/sh进去的容器运行可执行文件报not found的问题
- 【哲思与实战】程序设计之道
- 深度学习模型压缩与加速技术(七):混合方式
- OneSpin | 解决IC设计中的硬件木马和安全信任问题
- Implement secondary index with Gaussian redis
猜你喜欢

Data island is the first danger encountered by enterprises in their digital transformation

MRS离线数据分析:通过Flink作业处理OBS数据

力扣 2319. 判断矩阵是否是一个 X 矩阵
![[philosophy and practice] the way of program design](/img/c8/93f2ac7c5beb95f64b7883ad63c74c.jpg)
[philosophy and practice] the way of program design

复杂因子计算优化案例:深度不平衡、买卖压力指标、波动率计算

整型int的拼接和拆分

网络原理(1)——基础原理概述

Machine learning notes - explore object detection datasets using streamlit

不落人后!简单好用的低代码开发,快速搭建智慧管理信息系统

有了ST7008, 蓝牙测试完全拿捏住了
随机推荐
Opencv learning notes high dynamic range (HDR) imaging
力扣 88.合并两个有序数组
力扣674. 最长连续递增序列
基于深度学习的目标检测的更新迭代总结(持续更新ing)
Force buckle 912 Sort array
使用高斯Redis实现二级索引
School 1 of vulnhub
I Basic concepts
【论文阅读】MAPS: Multi-agent Reinforcement Learning-based Portfolio Management System
Vulnhub tre1
Airiot helps the urban pipe gallery project, and smart IOT guards the lifeline of the city
AADL Inspector 故障树安全分析模块
Spark 判断DF为空
如何满足医疗设备对安全性和保密性的双重需求?
EasyGBS级联时,上级平台重启导致推流失败、画面卡住该如何解决?
Nebula importer data import practice
第二十章 使用工作队列管理器(三)
静态测试工具
深度学习模型压缩与加速技术(七):混合方式
AIRIOT助力城市管廊工程,智慧物联守护城市生命线