调用APIRouter的 __call__函数

nova/wsgi.py

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 @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

  当osapi_compute_app_v2接收到HTTP请求时,根据类的继承关系, 将调用nova.wsgi.Router.__call__函数,如上所示。查看一下webob.dec.wsgify 的源码,发现如果函数返回的是wsgi app时,它还会被继续调用,并返回它的处理结果。

3.2.1  self._router 为routes.middleware.RoutesMiddleware实例,所以会调用routes.middleware.RoutesMiddleware.__call__函数,该函数调用routes.mapper.routematch来获取HTTP请求的URL所映射的controller等参数,以{"controller":Resource(Controller()), "action": funcname, "project_id": uuid, ...}的格式放在match中。并设置如下的environ变量,方便后面调用的self._dispatch访问。

environ['wsgiorg.routing_args'] = ((url), match)
environ['routes.route'] = route
environ['routes.url'] = url

最后调用self._dispatch()。 self._dispatch通过前面设置的environ['wsgiorg.routing_args']来找到url对应的controller,并返回该controller。

3.2.2  这里的controller就是在APIRouter初始化中设置的controller,也就是使用相应Controller类初始化的Resource实例。所以接着调用nova.api.openstack.wsgi.Resource.__call__函数,该函数通过environ['wsgiorg.routing_args']获取上面设置的match,该match有一个action属性,它指定了所要调用Controller成员函数的名字,以及其它相关的调用参数。在我们定义Controller的成员函数时,一般需要通过nova.api.openstack.wsgi.{serializers, deserializers}来指定解释body内容的模板,可以是xml或者json格式的。前面说过重定义nova.api.openstack.urlmap.URLMap的目的是为了判断content_type。Resource接着在解析body时会参考content_type,然后调用相应的解析器进行body解析(如XMLDeserializer、JSONDeserializer),接着将解析出的参数更新进action_args,使用action_args来调用Controller成员函数,即最终的http请求处理函数。最后将执行结果使用指定的序列化器序列化,并返回结果。

3.2.3  这里特别说明一下对常见RESTful请求之外的action请求的处理。以/servers/xxx/action请求为例,请求调用的函数实际包含在请求的body中。经过routes.middleware.RoutesMiddleware的__call__函数解析后,此时即将调用的Resource已经确定为哪个模块中的Controller所构建的Resource,而action参数为"action",接下来在Resource的__call__函数里面会因为action=="action"从而开始解析body的内容,找出Controller中所对应的方法。Controller在构建的过程中会由于MetaClass的影响将其所有action类型的方法填入一个字典中,key由每个_action_xxx方法前的@wsgi.action('xxx')装饰函数给出,value为每个_action_xxx方法的名字(从中可以看出规律,在body里面请求的方法名前加上_aciton_即为Controller中对应调用的方法)。之后在使用Controller构建Resource对象的过程中会向Resource注册该Controller的这个字典中的内容。这样,只需在请求的body中给出调用方法的key,然后就可以找到这个key所映射的方法,最后在Resource的__call__函数中会调用Controller类的这个函数!

参考文档:

http://www.it165.net/pro/html/201407/17020.html

nova-api源码分析(APP的调用)的更多相关文章

  1. Spring源码分析之`BeanFactoryPostProcessor`调用过程

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 本文内容: AbstractApplicationContext#refresh前部分的一点小内容 ...

  2. Openstack Nova 源码分析 — RPC 远程调用过程

    目录 目录 Nova Project Services Project 的程序入口 setuppy Nova中RPC远程过程调用 nova-compute RPC API的实现 novacompute ...

  3. mybatis源码分析(方法调用过程)

    十一月月底,宿舍楼失火啦,搞得20多天没有网,目测直到放假也不会来了... 正题 嗯~,其实阅读源码不是为了应付面试,更重要的让你知道,大师是怎样去写代码的,同样是用Java,为啥Clinton Be ...

  4. Mybatis源码分析之存储过程调用

    这一篇博客我们学习一下Mybatis调用存储过程的使用和运行流程.首先我们先创建一个简单的存储过程 DELIMITER $ CREATE PROCEDURE mybatis.ges_user_coun ...

  5. requests库核心API源码分析

    requests库是python爬虫使用频率最高的库,在网络请求中发挥着重要的作用,这边文章浅析requests的API源码. 该库文件结构如图: 提供的核心接口在__init__文件中,如下: fr ...

  6. jQuery1.11源码分析(8)-----jQuery调用Sizzle引擎的相关API

    之所以把这部分放在这里,是因为这里用到了一些基本API,前一篇介绍过后才能使用. //jQuery通过find方法调用Sizzle引擎 //jQuery通过find方法调用Sizzle引擎 jQuer ...

  7. MapReduce新版客户端API源码分析

    使用MapReduce新版客户端API提交MapReduce Job需要使用 org.apache.hadoop.mapreduce.Job 类.JavaDoc给出以下使用范例. // Create ...

  8. 3. 源码分析---SOFARPC客户端服务调用

    我们首先看看BoltClientProxyInvoker的关系图 所以当我们用BoltClientProxyInvoker#invoke的时候实际上是调用了父类的invoke方法 ClientProx ...

  9. Spring源码分析之AOP从解析到调用

    正文: 在上一篇,我们对IOC核心部分流程已经分析完毕,相信小伙伴们有所收获,从这一篇开始,我们将会踏上新的旅程,即Spring的另一核心:AOP! 首先,为了让大家能更有效的理解AOP,先带大家过一 ...

  10. 9.源码分析---SOFARPC是如何实现故障剔除的?

    SOFARPC源码解析系列: 1. 源码分析---SOFARPC可扩展的机制SPI 2. 源码分析---SOFARPC客户端服务引用 3. 源码分析---SOFARPC客户端服务调用 4. 源码分析- ...

随机推荐

  1. 使用 spring-boot-devtools 进行热部署

    2019/3/5 更新: 发现热部署不生效,出现页面显示error的错误,然后在 application.properties 中注释了下面两行成功实现热部署(直接删掉也可以) #spring.dev ...

  2. SpringBoot整合Mybatis之进门篇

    已经有好些日子没有总结了,不是变懒了,而是我一直在奋力学习springboot的路上,现在也算是完成了第一阶段的学习,今天给各位总结总结. 之前在网上找过不少关于springboot的教程,都是一些比 ...

  3. Mysql_临时表

    CREATE TEMPORARY TABLE test_info ( test_name ) NOT NULL, test_totail ,) NOT NULL DEFAULT 0.00, test_ ...

  4. hdu 2036:改革春风吹满地(叉积求凸多边形面积)

    改革春风吹满地 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  5. tomcat-内存溢出java.lang.OutOfMemoryErrory:PermGen space解决方法

    如果是PermGen space方法区内存溢出,可尝试加大MaxPermSize,如果是heap space 堆内存移除,可尝试修改Xmx 正常解决方法: 在注释下的第一行添加: JAVA_OPTS= ...

  6. 如何使用URLOS进行docker应用开发

    使用Docker技术可以帮助企业快速水平扩展服务,从而到达弹性部署业务的能力.在云服务概念兴起之后,Docker的使用场景和范围进一步发展,如今在微服务架构越来越流行的情况下,微服务+Docker的完 ...

  7. 微软职位内部推荐-Senior Software Engineer - Back End

    微软近期Open的职位: SharePoint is a multi-billion dollar enterprise business that has grown from an on-prem ...

  8. 记初学net-SNMP

    自从弄完那个jsp的网盘(其实还是个烂摊子),这几天一直在研究snmp. 有需求就激发动力,对,人都是被逼出来的.五一这几天,天天搁这坐着,毫无头绪. 下面切入正题. 要做一个监控园区网在线数的平台, ...

  9. 设置matplotlib画图支持中文显示

    1.安装中文字体 git clone https://github.com/tracyone/program_font && cd program_font && ./ ...

  10. Leetcode题库——47.全排列II

    @author: ZZQ @software: PyCharm @file: permuteUnique.py @time: 2018/11/16 13:34 要求:给定一个可包含重复数字的序列,返回 ...