小辣椒开发笔记

应用启动流程

根据WSGI协议,应用程序会接收到web server提供的environ与start_response两个参数,我们只需要从environ参数中提取相关信息并返回一个可迭代对象即可。

flask对该流程的处理逻辑如下:

def wsgi_app(self, environ, start_response):
    
    #根据提供的environ创建请求上下文对象,并入栈
    ctx = self.request_context(environ)
    ctx.push()
    error = None

    try:
        # 正确的请求处理路径,会通过路由找到对应的处理函数
        response = self.full_dispatch_request()
    except Exception as e:
        # 错误处理,默认是 InternalServerError 错误处理函数,客户端会看到服务器 500 异常
        error = e
        response = self.handle_exception(e)
    return response(environ, start_response)

首先对出入的environ参数创建一个RequestContext请求上下文对象,该对象包含着HTTP请求所含有的所有信息。之后请求上下文建立成功后,会执行response = self.full_dispatch_request(),该语句会根据请求中的路由找到相应的处理函数来处理请求,并将该函数的返回值处理后生成response对象返回。在处理请求的过程中,若遇到了异常,则该异常会被捕获并交给handle_exception(e)函数处理,该函数接受一个异常对象并返回一个response对象。之后获取response对象后,调用该对象即可。(所以说我们的应用程序好像更像是一个中间件?)

路由处理

    def dispatch_request(self):
        rule = request.url_rule
        return self.view_functions[rule.endpoint](**request.view_args)

由路由到函数的映射关系为路由->端点->函数,在werkzeug库中已经提供了一系列的类供我们处理路由与端点的关系,而我们需要做的只是处理端点到函数的映射关系,该关系用一个字典即可轻松搞定。由代码可知我们会在生成request对象的时候根据路由获取对应的端点,在处理请求的时候我们只需根据端点调用相应函数即可。而对于端点与函数的映射关系,我们提供了一个简单的函数用于注册:

    def add_url_rule(self, path, view_func, endpoint=None, methods=None):
        if endpoint is None:
            endpoint = view_func.__name__

        if methods is None:
            methods = getattr(view_func, "methods", None) or ("GET",)

        rule = Rule(path, endpoint=endpoint, methods=methods)
        self.url_map.add(rule)
        self.view_functions[endpoint] = view_func

异常处理

    def handler_exceptions(self, e):
        exc_type = type(e)

        if exc_type in self.handler_map:
            handler = self.handler_map.get(exc_type)
            return handler(e)
        else:
            raise e

请求处理过程中触发异常的话,异常会被捕获并交给该函数处理,该函数接受一个异常后,根据异常所属的类查看该异常的处理方式是否被注册,若已被注册,则将该异常抛给注册的错误处理器处理,并返回响应。若未被注册,则将异常再次抛出,触发程序错误。用于注册错误处理器的函数如下:

    def register_error_handler(self, exc_class_or_code, handler):
        exc_class = _find_exceptions(exc_class_or_code)
        self.handler_map[exc_class] = handler

版权声明:本文为fuck-you原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/fuck-you/p/13022529.html