花了两个星期,我终于把 WSGI 整明白了 (6)

经过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 简介

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwppjj.html