经过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类的这个函数!
其实我在上面我们打印 match 对象时,就已经将对应的函数打印出来了。
这边以 nova show(展示资源为例),来理解一下。
当你调用 nova show [uuid] 命令,novaclient 就会给 nova-api 发送一个http的请求
nova show 1c250b15-a346-43c5-9b41-20767ec7c94b通过打印得到的 match 对象如下
{'action': u'show', 'controller': <nova.api.openstack.wsgi.ResourceV21 object at 0x667bad0>, 'project_id': u'2ac17c7c792d45eaa764c30bac37fad9'}其中 action 就是对应的处理函数,而controller 就对应的 Resource 对象,project_id 是租户id(你可以不理会)。
继续看 ResourceV21 类里的 __call__ 函数的代码。
图示地方,会从 environ 里获取中看到获取 action 的具体代码
我将这边的 action_args打印出来
{'action': 'show', 'project_id': '2ac17c7c792d45eaa764c30bac37fad9', 'id': '1c250b15-a346-43c5-9b41-20767ec7c94b'}其中 action 还是是函数名,id 是要操作的资源的唯一id标识。
在 __call__ 的最后,会 调用 _process_stack 方法
在图标处,get_method 会根据 action(函数名) 取得处理函数对象。
meth :<bound method ServersController.show of <nova.api.openstack.compute.servers.ServersController object at 0x7be3750>>最后,再执行这个函数,取得 action_result,在 _process_stack 会对 response 进行初步封装。
然后将 response 再返回到 wsgify ,由这个专业的工具函数,进行 response 的最后封装和返回给客户端。
至此,一个请求从发出到响应就结束了。
附录:参考文章PEP 3333 中文翻译
nova-api源码分析(APP的调用)
Python Route总结
Python routes Mapper 的使用
详解 Paste deploy
paste.ini 文件使用说明
PasteDeploy 小白教程
WSGI 两种架构图
伯乐在线:Python Web开发最难懂的WSGI协议
WSGI 简介