Flask中客户端 - 服务器 - web应用程序 是如何处理request生成response的?

文章转载自https://blog.csdn.net/weixin_37923128/article/details/80992645 , 感谢原作者

当客户端向服务器发送一个请求时,服务器会将请求转发给web应用程序,应用程序处理完这个请求后将会返回一个response。在这篇文章我们分析一下flask怎样处理request,又是怎样生成response的,同时我们应该思考,在这个过程中,flask是怎样让url、endpoint、视图函数一一对应的。

一旦web应用接收到request,flask就会调用Flask类的call函数。在wsgi_app()函数中,我们看到,在调用了full_dispatch_request()函数后,就生成了response(Response类实例)。

 1 class Flask:
 2     def __call__(self, environ, start_response):
 3         return self.wsgi_app(environ, start_response)
 4 
 5     def wsgi_app(self, environ, start_response):
 6         ctx = self.request_context(environ)
 7         error = None
 8         try:
 9             try:
10                 ctx.push()
11                 response = self.full_dispatch_request()
12             except Exception as e:
13                 error = e
14                 response = self.handle_exception(e)
15            except:
16                error = sys.exc_info()[1]
17                raise
18         return response(environ, start_response)
19     finally:
20         if self.should_ignore_error(error):
21             error = None
22         ctx.auto_pop(error)

在函数full_dispatch_request中,我们看到了dispatch_request函数,一路寻找下去,在这个函数里找到了view_functions这个字典。这个字典被多个函数在多个函数中出现。

 1 def full_dispatch_request(self):
 2     self.try_trigger_before_first_request_functions()
 3     try:
 4         request_started.send(self)
 5         rv = self.preprocess_request()
 6         if rv is None:
 7             rv = self.dispatch_request()
 8     except Exception as e:
 9         rv = self.handle_user_exception(e)
10     return self.finalize_request(rv)
11 
12 def dispatch_request(self):
13     req = _request_ctx_stack.top.request
14     if req.routing_exception is not None:
15     self.raise_routing_exception(req)
16     rule = req.url_rule
17 
18     if getattr(rule, 'provide_automatic_options', False) \
19         and req.method == 'OPTIONS':
20         return self.make_default_options_response()
21 return self.view_functions[rule.endpoint](**req.view_args)
22 
23 self.view_functions = {}

那这个add_url_rule函数又是在哪里被调用的呢?往下看。

 1 def add_url_rule(self, rule, endpoint=None, view_func=None,provide_automatic_options=None, **options):
 2     if endpoint is None:
 3         endpoint = _endpoint_from_view_func(view_func)
 4         options['endpoint'] = endpoint
 5         methods = options.pop('methods', None)
 6 
 7 # if the methods are not given and the view_func object knows its
 8 # methods we can use that instead. If neither exists, we go with
 9 # a tuple of only ``GET`` as default.
10     if methods is None:
11         methods = getattr(view_func, 'methods', None) or ('GET',)
12     if isinstance(methods, string_types):
13         raise TypeError('Allowed methods have to be iterables of strings, ''for example: @app.route(..., methods=["POST"])')
14     methods = set(item.upper() for item in methods)
15 
16 # Methods that should always be added
17     required_methods = set(getattr(view_func, 'required_methods', ()))
18 
19 # starting with Flask 0.8 the view_func object can disable and
20 # force-enable the automatic options handling.
21     if provide_automatic_options is None:
22         provide_automatic_options = getattr(view_func,'provide_automatic_options', None)
23 
24     if provide_automatic_options is None:
25         if 'OPTIONS' not in methods:
26             provide_automatic_options = True
27             required_methods.add('OPTIONS')
28         else:
29             provide_automatic_options = False
30 
31         # Add the required methods now.
32         methods |= required_methods
33 
34         rule = self.url_rule_class(rule, methods=methods, **options)
35         rule.provide_automatic_options = provide_automatic_options
36 
37         self.url_map.add(rule)
38         if view_func is not None:
39             old_func = self.view_functions.get(endpoint)
40                 if old_func is not None and old_func != view_func:
41                     raise AssertionError('View function mapping is overwriting an ''existing endpoint function: %s' % endpoint)
42             self.view_functions[endpoint] = view_func

看到这里就应该明白了。在我们写的web应用程序中,往往需要对视图函数添加路由修饰,如:app.route(‘/’)。正是在路由函数中调用了add_url_rule函数,而这个函数负责绑定相应的视图函数、url、以及endpoint。由此,这三个参数建立联系。而后,在程序运行中,当web程序收到请求后,根据请求中的url找到endpoint,再根据endpoint找到视图函数,然后调用视图函数,在视图函数中,会处理那些需要处理的值(return self.view_functionsrule.endpoint)。接下来这个函数的返回值会交给finalize_request()函数处理。

1 def route(self, rule, **options):
2     def decorator(f):
3         endpoint = options.pop('endpoint', None)
4         self.add_url_rule(rule, endpoint, f, **options)
5         return f
6     return decorator

正是在这个函数里,生成了response。(response是Response类的实例),最终,这个response被返回给客户端,然后显示为页面。

 1 def finalize_request(self, rv, from_error_handler=False):
 2     response = self.make_response(rv)
 3     try:
 4         response = self.process_response(response)
 5         request_finished.send(self, response=response)
 6     except Exception:
 7         if not from_error_handler:
 8         raise
 9             self.logger.exception('Request finalizing failed with an ''error while handling an error')
10     return response

猜你喜欢

转载自www.cnblogs.com/luke20181010/p/10563419.html