Falsk源码刨析(二) : 请求到响应的流程源码刨析

客户端发送过来请求之后,首先会携带参数调用app对象__call__()的方法,该方法中只完成了一件事,就是调用wsgi_app()方法

    def __call__(self, environ, start_response):
        /*
        @environ :  创建的WSGI环境
        @start_response :  接受状态码的响应对象
		*/
        return self.wsgi_app(environ, start_response)

进入到wsgi_app()方法的源码中,可以得知wsgi_app()方法的重要信,该函数类似于CPU完成着对整个框架请求得调度。

 def wsgi_app(self, environ, start_response):
        with self.request_context(environ):   
            rv = self.preprocess_request()
            if rv is None :
                rv = self.dispatch_request() 
            response = self.make_response(rv)
            response = self.process_response(response)
            return response(environ, start_response)

request_context(environ)函数源码刨析 :
通过进入request_context(environ)函数可以看出request_context(environ)其实是实现了上下文管理器得包装类,该上下文管理器在请求进入之前被创建,在该管理器中有一点相当重要:就是__enter__中得 _request_ctx_stack.push(self),不难理解该方法可以使得请求在进入时被创建,之后被推送到_request_ctx_stack,在请求结束时会被相应的移除。

   def request_context(self, environ) :
        return _RequestContext(self, environ)
   
   class _RequestContext(object):
    def __init__(self, app, environ) :

        self.app = app
        #为WSGI环境创建Url适配器
        self.url_adapter = app.url_map.bind_to_environ(environ)
        #为SWGI环境创建请求对象
        self.request = app.request_class(environ)

        self.session = app.open_session(self.request)

        self.g = _RequestGlobals()
        self.flashes = None


    def __enter__(self):
        _request_ctx_stack.push(self)

    def __exit__(self, exc_type, exc_value, tb):
        # 在调试模式(debug mode)而且有异常发生时,不要移除(pop)请求堆栈。
        # 这将允许调试器(debugger)在交互式shell中仍然可以获取请求对象。
        if tb is None or not self.app.debug:
            _request_ctx_stack.pop()

上下文管理器被创建完成之后,系统会调用preprocess_request()方法从before_request_funcs中逐一遍历获取访问对象,那么before_request_funcs中到底放的是什么 ?官方给出得解释是在请求被分发前需要调用得函数,其中存放得请求转发之前存放函数【端点函数】。

 def preprocess_request(self)for func in self.before_request_funcs:
            rv = func()
            if rv is not None:
                return rv

在实际的请求分发之前调用,而且将会逐一调用before_request_funcs中函数。如果其中某一个函数返回一个值,这个值将会作为视图返回值,处理并停止进一步的请求处理。
如果调用preprocess_request函数没有函数值,那么就会执行请求分发得操作,请求分发的方法封装在dispatch_request()

    def dispatch_request(self):
        try:
            #匹配成功,返回视图函数
            endpoint, values = self.match_request()
            return self.view_functions[endpoint](**values)
        except HTTPException as e:
            handler = self.error_handlers.get(e.code)
            if handler is None:
                return e
            return handler(e)
        except Exception as e:
            handler = self.error_handlers.get(500)
            if self.debug or handler is None:
                raise
            return handler(e)
  def match_request(self):
        rv = _request_ctx_stack.top.url_adapter.match()
        request.endpoint, request.view_args = rv
        return rv

请求转发的流程 :在_request_ctx_stack中通过适配器利用url映射匹配视图函数,这种情况下会出现两种可能,一种是匹配成功一种是匹配异常,对于前一种情况,会通过view_functions映射表,将视图函数组装完成直接返回,如果匹配失败,难免查询异常处理器将结果返回。到这里并没有结束,有时候,返回的结果中,返回值并非真正响应的对象,所以需要将返回值分装称为一个真正得响应对象,make_response就提供了这种便利

/*
        @response_class  :这个对象将被直接返回
        @str   :使用这个字符串作为主体创建一个请求对象
        @unicode  :将这个字符串进行utf-8编码后作为主体创建一个请求对象
        @tuple :使用这个元组的内容作为参数创建一个请求对象
        @a WSGI function : 这个函数将作为WSGI程序调用并缓存为响应对象
*/
    def make_response(self, rv):
        if isinstance(rv, self.response_class):
            return rv
        if isinstance(rv, string):
            return self.response_class(rv)
        if isinstance(rv, tuple):
            return self.response_class(*rv)
        return self.response_class.force_type(rv,request.environ) 

返回响应对象之前,需要对响应得对象进行再次加工,或者在响应之前执行其他操作process_response中提供了将session于响应对象绑定的实例以及调用请求转发完成之后需要执行的操作,有时候需要对其进行其他操作的处理,那么可以重写该方法。

  session = _request_ctx_stack.top.session
        if session is not None:
            self.save_session(session, response) 
        for handler in self.after_request_funcs :
            response = handler(response)
        return response

至此一个完成的请求的过程基本完成。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值