Flask中一次请求到响应的流程,flask响应,未经作者许可,禁止转载!
Flask中一次请求到响应的流程,flask响应,未经作者许可,禁止转载!
本文作者: 编橙之家 - 王海波 。未经作者许可,禁止转载!欢迎加入编橙之家 专栏作者。
1、首先根据WSGI发送的environ变量获取请求上下文,主要是根据函数ctx = self.request_context(environ),然后将该请求上下文推入全局变量_request_ctx_stack中(ctx.push()).
def request_context(self, environ): return RequestContext(self, environ)
2、得到请求后,要触发第一次请求函数,如果是该应用是第一次实例化,并存在第一次请求之前函数(存在before_first_req_func字典中中),会调用存在该字典中的函数。当然一个实例也只执行一次,即在初始化的时候执行。
3、会发送请求开始信号,request_started,告知subscriber请求开始了。
4、如果存在before_request装饰的函数(函数位置在before_request_func字典中),那么在调用正常请求前会调用该函数。
@setupmethod def before_request(self, f): """Registers a function to run before each request. The function will be called without any arguments. If the function returns a non-None value, it's handled as if it was the return value from the view and further request handling is stopped. """ self.before_request_funcs.setdefault(None, []).append(f) return f
从函数可以看到,这是一个装饰器,被该装饰器修饰的函数会添加到字典中。
5、调用正常的请求,返回一个该请求函数的值。 调用请求的源代码:
def dispatch_request(self): """Does the request dispatching. Matches the URL and returns the return value of the view or error handler. This does not have to be a response object. In order to convert the return value to a proper response object, call :func:make_response. req = _request_ctx_stack.top.request if req.routing_exception is not None: self.raise_routing_exception(req) rule = req.url_rule # if we provide automatic options for this URL and the # request came with the OPTIONS method, reply automatically if getattr(rule, 'provide_automatic_options', False) and req.method == 'OPTIONS': return self.make_default_options_response() # otherwise dispatch to the handler for that endpoint return self.view_functions[rule.endpoint](**req.view_args)
6、将请求函数返回值构造成响应类。
def make_response(self, rv): """Converts the return value from a view function to a real response object that is an instance of :attr:response_class. The following types are allowed for `rv`: ======================= =========================================== :attr:`response_class` the object is returned unchanged :class:`str` a response object is created with the string as body :class:`unicode` a response object is created with the string encoded to utf-8 as body a WSGI function the function is called as WSGI application and buffered as response object :class:`tuple` A tuple in the form ``(response, status, headers)`` or ``(response, headers)`` where `response` is any of the types defined here, `status` is a string or an integer and `headers` is a list or a dictionary with header values. ======================= =========================================== :param rv: the return value from the view function .. versionchanged:: 0.9 Previously a tuple was interpreted as the arguments for the response object. """ status_or_headers = headers = None if isinstance(rv, tuple): rv, status_or_headers, headers = rv + (None,) * (3 - len(rv)) if rv is None: raise ValueError('View function did not return a response') if isinstance(status_or_headers, (dict, list)): headers, status_or_headers = status_or_headers, None if not isinstance(rv, self.response_class): # When we create a response object directly, we let the constructor # set the headers and status. We do this because there can be # some extra logic involved when creating these objects with # specific values (like default content type selection). if isinstance(rv, (text_type, bytes, bytearray)): rv = self.response_class(rv, headers=headers, status=status_or_headers) headers = status_or_headers = None else: rv = self.response_class.force_type(rv, request.environ) if status_or_headers is not None: if isinstance(status_or_headers, string_types): rv.status = status_or_headers else: rv.status_code = status_or_headers if headers: rv.headers.extend(headers) return rv
7、会调用after_request装饰的函数,并返回响应类。 源代码:
def process_response(self, response): """Can be overridden in order to modify the response object before it's sent to the WSGI server. By default this will call all the :meth:after_request decorated functions. :param response: a :attr:`response_class` object. :return: a new response object or the same, has to be an instance of :attr:`response_class`. """ ctx = _request_ctx_stack.top bp = ctx.request.blueprint funcs = ctx._after_request_functions if bp is not None and bp in self.after_request_funcs: funcs = chain(funcs, reversed(self.after_request_funcs[bp])) if None in self.after_request_funcs: funcs = chain(funcs, reversed(self.after_request_funcs[None])) for handler in funcs: response = handler(response) if not self.session_interface.is_null_session(ctx.session): self.save_session(ctx.session, response) return response
8、发送请求结束信号,request_finished.
9、应用将响应发送给客户端,利用响应函数response(environ, start_response)。
………………………………………………………………
下面是Flask请求响应的主函数:
def wsgi_app(self, environ, start_response): """The actual WSGI application. :param environ: a WSGI environment :param start_response: a callable accepting a status code, a list of headers and an optional exception context to start the response """ ctx = self.request_context(environ) ctx.push() error = None try: try: response = self.full_dispatch_request() except Exception as e: error = e response = self.make_response(self.handle_exception(e)) return response(environ, start_response) finally: if self.should_ignore_error(error): error = None ctx.auto_pop(error) def call(self, environ, start_response): """Shortcut for :attr:wsgi_app.""" return self.wsgi_app(environ, start_response) def repr(self): return '' % ( self.class.name, self.name, )
打赏支持我写出更多好文章,谢谢!
打赏作者
打赏支持我写出更多好文章,谢谢!
任选一种支付方式
相关内容
- Flask 框架中 SQLAlchemy 使用时的乱码问题,flasksqlalchemy
- Flask使用小结,flask小结,未经作者许可,禁止转载!
- Flask 框架作者希望看到的 Python,flaskpython,未经许可,禁
- 基于 Spark 和 Flask 的一个可伸缩的电影推荐系统,spar
- Python和Flask真是太强大了,PythonFlask强大,未经许可,禁
- 30分钟编写一个Flask应用,30分钟编写flask,未经许可,禁
- 在Linux上使用Python和Flask创建你的第一个应用,pythonfl
- Scrapy + Flask + Mongodb + Swift 开发爬虫全攻略(1),scrap
- Scrapy+Flask+Mongodb+Swift开发全攻略(2),scrapyflask,第一件
- Scrapy+Flask+Mongodb+Swift开发全攻略(3),scrapyflask, 那么我
评论关闭