python-flask-路由匹配源码分析

Posted Cool

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python-flask-路由匹配源码分析相关的知识,希望对你有一定的参考价值。

 

@app.route(/)
def hello_world():
    return Hello World!

 

第1步:

class Flask(_PackageBoundObject):
    def route(self, rule, **options):
        def decorator(f):                 #f = hello_world
       #1.1获取别名
endpoint
= options.pop(endpoint, None)
       #1.2 self.add_url_rule(rule, endpoint, f,
**options) return f return decorator

第1.2步:

class Flask(_PackageBoundObject):
    def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
        #1.2.1如果别名是None,执行_endpoint_from_view_func函数
        if endpoint is None:
            endpoint = _endpoint_from_view_func(view_func)
     #1.2.2 给endpoint赋值 options[
endpoint] = endpoint
     #1.2.3 获取允许的请求方法 methods
= options.pop(methods, None)      #1.2.4如果方法为None if methods is None:
       #默认为GET methods
= getattr(view_func, methods, None) or (GET,)
     #1.2.5如果方法是字符串,抛出异常: 必须是methods=["POST"]这样可迭代的
if isinstance(methods, string_types): raise TypeError(Allowed methods have to be iterables of strings, for example: @app.route(..., methods=["POST"]))
     #1.2.6把方法变成大写 methods
= set(item.upper() for item in methods)      #1.2.7把匹配url和允许请求的方法封装到了Rule的一个对象中 rule = self.url_rule_class(rule, methods=methods, **options)
     #self.url_rule_class = Rul
     #1.2.8
self.url_map.add(rule)
      #self.url_map = Map()
if view_func is not None:        #1.2.9 此步完成后: {"别名":被装饰的函数名} self.view_functions[endpoint] = view_func

第1.2.1步:

def _endpoint_from_view_func(view_func):
    #返回被装饰的函数名
    return view_func.__name__

第1.2.8步:

class Map(object):
    def add(self, rulefactory):
        #1.2.8.1
        for rule in rulefactory.get_rules(self):
       #1.2.8.2 Rule对象进行re正则绑定 rule.bind(self)
       #1.2.8.3 添加到self._rules列表中,此时列表中就有了url self._rules.append(rule)
       #1.2.8.4 此步完成后: {"别名":url} self._rules_by_endpoint.setdefault(rule.endpoint, []).append(rule)

第1.2.8.1步:

class Rule(RuleFactory):
  def get_rules(self, map): yield self
   #返回Rule对

第1.2.8.2步:

class Rule(RuleFactory):
  def bind(self, map, rebind=False):
     #1.2.8.2.1
self.compile()

第1.2.8.2.1步: 看不懂,猜里面是把url进行了re正则处理

class Rule(RuleFactory):
    def compile(self):
        if self.map.host_matching:
            domain_rule = self.host or ‘‘
        else:
            domain_rule = self.subdomain or ‘‘

        self._trace = []
        self._converters = {}
        self._static_weights = []
        self._argument_weights = []
        regex_parts = []

        def _build_regex(rule):
            index = 0
            for converter, arguments, variable in parse_rule(rule):
                if converter is None:
                    regex_parts.append(re.escape(variable))
                    self._trace.append((False, variable))
                    for part in variable.split(/):
                        if part:
                            self._static_weights.append((index, -len(part)))
                else:
                    if arguments:
                        c_args, c_kwargs = parse_converter_args(arguments)
                    else:
                        c_args = ()
                        c_kwargs = {}
                    convobj = self.get_converter(
                        variable, converter, c_args, c_kwargs)
                    regex_parts.append((?P<%s>%s) % (variable, convobj.regex))
                    self._converters[variable] = convobj
                    self._trace.append((True, variable))
                    self._argument_weights.append(convobj.weight)
                    self.arguments.add(str(variable))
                index = index + 1

        _build_regex(domain_rule)
        regex_parts.append(\\|)
        self._trace.append((False, |))
        _build_regex(self.is_leaf and self.rule or self.rule.rstrip(/))
        if not self.is_leaf:
            self._trace.append((False, /))

        if self.build_only:
            return
        regex = r^%s%s$ % (
            u‘‘.join(regex_parts),
            (not self.is_leaf or not self.strict_slashes) and
            (?<!/)(?P<__suffix__>/?) or ‘‘
        )
        self._regex = re.compile(regex, re.UNICODE)

 

 到此为止:

路由规则列表里新增了一条绑定正则的rule ;{"别名":rule} ;{"别名":被装饰的函数名}


















以上是关于python-flask-路由匹配源码分析的主要内容,如果未能解决你的问题,请参考以下文章

python-flask复习——- flask请求上下文源码解读http聊天室单聊/群聊(基于gevent-websocket)

python-flask复习—— 装饰器的坑及解决办法flask中的路由/实例化配置/对象配置/蓝图/特殊装饰器(中间件重定义错误页面)

Orchard源码分析(7.1):Routing(路由)相关

Android 插件化VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )(代码片段

Android 逆向整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )(代码片段

Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段