一个WSGI Application如果是一个class的实例,那么这个class必须实现一个回调函数:__call__()。当一个HTTP Request过来时,WebServer就会调用这个实例(WSGI Application)的”__call__”函数进行响应。对于class APIRouter来说,它的__call__函数,定义在它的父类class Router中,如下图所示:
要想了解HTTP Request过来时Core Service的处理流程,首先得了解class Router。下面先分析class Router的代码,它的代码从github上获取,获取路径如下:
相关代码如下:
class Router(object):
def __init__(self, mapper):
self.map = mapper
self._router = routes.middleware.RoutesMiddleware(self._dispatch,
self.map)
@webob.dec.wsgify(RequestClass=Request)
def __call__(self, req):
return self._router
这段代码用到了class RoutesMiddleware, 它的代码从github上获取,获取路径如下
相关代码如下:
class RoutesMiddleware(object):
def __init__(self, wsgi_app, mapper, use_method_override=True,
path_info=True, singleton=True):
self.app = wsgi_app
self.mapper = mapper
def __call__(self, environ, start_response):
response = self.app(environ, start_response)
return response
class RoutesMiddleware也是一个WSGI Application类型的class,因此,它必须实现一个__call__函数,最终调用当初传递给它的class Router的静态函数_dispatch。代码顺序图如下:
该图表达的流程如下:
1 Web Client发送HTTP Request请求到达Web Server(即客户端调用Neutron Server的Core Server API(RESTful));
2 Web Server调用它的WSGI Application(class APIRouter的实例)的__call__函数,即调用class APIRouter父类class Router的__call__函数;
3 class Router的__call__函数,返回了class RoutersMiddleware的一个实例;
4 Web Server继续调用这个class RoutersMiddleware实例的__call__函数;
5 class RoutersMiddleware的__call__函数,再反过来调用class Router的静态函数_dispatch,它的代码如下:
@staticmethod
@webob.dec.wsgify(RequestClass=Request)
def _dispatch(req):
match = req.environ['wsgiorg.routing_args'][1]
if not match:
return webob.exc.HTTPNotFound()
app = match['controller']
return app
这段代码,有几点需要特别说明:
1 装饰模式
表明上看,这个函数仅仅是返回一个app(return app),但是因为这个函数是一个装饰模式,所以这个函数最终的效果不仅仅是返回一个app,还会执行这个app,如下(伪码):
return app(environ,start_response)
2 req.environ['wsgiorg.routing_args'][1]
req.environ['wsgiorg.routing_args'][1]是什么?又是谁给它赋的值?这两个问题,答案都在class RoutesMiddleware的__call__函数,代码如下:
class RoutesMiddleware(object):
def __init__(self, wsgi_app, mapper, use_method_override=True,
path_info=True, singleton=True):
self.app = wsgi_app
def __call__(self, environ, start_response):
config.mapper = self.mapper
match = config.mapper_dict
environ['wsgiorg.routing_args'] = ((url), match)
所以,我们再回过头看class Route的_dispatch函数的那两句代码:
match = req.environ['wsgiorg.routing_args'][1]
app = match['controller']
这就相对于如下代码:
app = mapper[‘controller’]
通过以上的代码梳理,再刷新一下class APIRouter的基本流程图,如下图:
该图更进一步:class Router的函数_dispatch继续寻找真命天子函数(app = mapper[‘controller’])来处理HTTP Request。