天天看點

openstack XXX-api分析

RESTful API: 表征狀态遷移,也就是說client端使用http的基本操作(主要四種:get, post, put, delete 對應增删改查)使服務端的資源狀态轉化;

WSGI: web server gateway interface  web服務網關接口,可以看作一個橋梁,一端連這服務端(wsgi server), 一端連接配接應用程式(wsgi app),橋體(wsgi middleware),也就是說wsgi server直接處理client端的http請求,将請求内容轉譯為應用app能夠處理的對象; 

  api服務是入口,主要把client端發送http請求映射到具體處理函數上,主要涉及三個子產品:

 paste.deploy: 建構openstack的wsgi服務, /etc下都有對應項目的paste的檔案,nova為例: /etc/nova/api-paste.ini, paste.deploy建構wsgi服務就是基于該配置檔案

webob: 對wsgi的請求和響應進行封裝(将wsgi與應用app的資訊進行處理,使用端更友善進行處理,可以放入wsgi子產品内了解)

routes: 定義url到内部函數的映射;    

  route 可以從url提取相應的參數,如controller,action或者其它使用者自己定義的變量

  openstack中的nova-api分析:

分析:

  1)webob.dec.wsgify是webob為WSGI應用程式提供的一個裝飾器,作用是将一個函數轉換成一個WSGI應用。

  2)routes.middleware.RoutesMiddleware,将接受到的url,自動調用map.match()方法,将url進行路由比對并将結果存入request請求的環境變量['wsgiorg.routing_args'],最後會調用其第一個參數給出的函數接口,即self.dispatch。

  3)map.connect 及map.resource均用來建立路由比對條件

  針對程式中的比對條件1  

  map.connect('/images',controller=a,action='search',conditions={'method':['GET']}) 

curl

路由比對結果 (程式中的route match result is)

curl請求得到的結果

curl -X GET http://localhost:8088/images

{'action': u'search', 'controller': <__main__.controller object at 0x10c2b10>}

"do search()"

  比對條件指定了curl的動作為GET ,通路路徑為images  對應的action 為search

   比對條件2 

    map.connect('name',"/{action}/{pid}",controller=a)

curl -X GET  http://localhost:8088/show/hihi

{'action': u'show', 'controller': <__main__.controller object at 0x2203b10>, 'pid': u'hihi'}

"do show()"

curl -X POST  http://localhost:8088/failfunc/test

{'action': u'failfunc', 'controller': <__main__.controller object at 0x2203b10>, 'pid': u'test'}

"has no action:failfunc"

    比對條件沒有指定curl的動作,是以所有的動作(PUT,POST,GET,。。)都比對,第二個curl請求,比對的action 為failfunc,pid為test,但是程式沒有定義failfunc函數,報錯

  比對條件3   

    map.resource("message","messages",controller=a)  ,map.resource内部定義了預設的比對條件

    第一個參數message為 member_name(資源名),第二個參數messages為collection_name(資源集合名),一般定義資源集合名為資源名的複數,我這裡随便取名

    collection_name作為通路的路徑名,且當沒有傳入參數controller時,controller=collection_name

    map.resource("message","messages",controller=a) 等同于以下比對條件:

      map.connect('/messages',controller=a,action='index',conditions={'method':['GET']})

      map.connect('/messages',controller=a,action='create',conditions={'method':['POST']})

      map.connect('/messages/{id}',controller=a,action='show',conditions={'method':['GET']})

      map.connect('/messages/{id}',controller=a,action='update',conditions={'method':['PUT']})

      map.connect('/messages/{id}',controller=a,action='delete',conditions={'method':['DELETE']})

    前兩條是針對整個資源集合的操作,後三條是針對資源集合中某個固定資源的操作 

openstack XXX-api分析

  這裡比對結果中的id為某個具體資源id,這裡亂取,後三條curl針對具體資源(id為12)的操作,前兩條是針對整個資源集合的操作

  當url傳入的id包含'.',會将'.'後的字元竄比對為format,如輸入的id 為 '12.hihi' ,比對id='12', format='hihi'

  比對條件4

    map.resource('message', 'messages',controller=a,

                        collection={'search':'GET','create_many':'POST'},

                        member={'update_many':'POST','delete_many':'POST'})

    map.resource除了預設的路由條件外,還可以額外的定義‘資源集合的方法’以及‘單個資源的方法’

    collection={'search':'GET','create_many':'POST'}       定義了資源集合方法 search,其curl動作為GET,create_many,其curl動作為POST

    member={'update_many':'POST','delete_many':'POST'}    定義了單個資源方法 update_many,其curl動作為POST,delete_many,其curl動作為POST

openstack XXX-api分析

  比對條件5 

    map.resource('message', 'messages',controller=a,path_prefix='/{projectid}',

                    collection={'list_many':'GET','create_many':'POST'},

                    member={'update_many':'POST','delete_many':'POST'})

    map.resource初始化時還可以指定curl通路路徑的字首路徑,如比對條件3及4沒有指定時,預設為collection_name(資源集合名)

    指定path_prefix後,路徑為path_prefix/collection_name

openstack XXX-api分析

    在路由5的條件下,添加一條

    map.resource('type', 'types',controller=other_controller,

                           parent_resource=dict(member_name='message',

                            collection_name='messages'),

                           path_prefix = '{projectid}/%s/:%s_id' %('nex','nexs'))

     curl -X POST  http://localhost:8088/proj1/nex/17/types

      比對nexs_id 為17,controller 為other_controller,  parent_resource的作用為形成name_prefix = 'message_',具體作用不詳,有待研究

  參考資料:http://routes.readthedocs.org/en/latest/restful.html

  疑問:

    resource中的controller對象的類定義必須要有__call__,要不然,比對後變為type(controller)為unicode,原因不明,有待研究