openstack XXX-api分析

简介: 一、概述RESTful API: 表征状态迁移,也就是说client端使用http的基本操作(主要四种:get, post, put, delete 对应增删改查)使服务端的资源状态转化;WSGI: web server gateway interface  web服务网关接口,可以看作一个桥...

一、概述

  • 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到内部函数的映射;    

二、python route 深入

  route 可以从url提取相应的参数,如controller,action或者其它用户自己定义的变量

 1 #routes中的Mapper
 2 #Mapper().connect    Mapper().match
 3 
 4 from routes import Mapper  
 5 map = Mapper()  
 6 map.connect(None,"error/{action}/{id}",controller="controller_obj") #定义匹配规则  
 7 result = map.match('error/myapp/4')  #匹配url='error/myapp/4'  
 8 #result 匹配结果  
 9 {'action': u'myapp', 'controller': u'controller_obj', 'id': u'4'}  
10 map.connect(None,"/message/:name",controller='my_contro')  #除 {} 外,:也可以作为匹配符号  
11 result = map.match('/message/12')  
12 #result 匹配结果  
13 {'controller': u'my_contro', 'name': u'12'}  

  openstack中的nova-api分析:

  1 #!/usr/bin/env/python  
  2 #coding=utf-8  
  3 from routes import Mapper  
  4 from routes import middleware  
  5 import webob.dec  
  6 from wsgiref.simple_server import make_server  
  7   
  8 class controller(object):  
  9     def __init__(self):  
 10         self.i = 1  
 11     def __call__(self):  
 12         print self.i  
 13     def search(self):  
 14         return "do search()"  
 15     def show(self):  
 16         return "do show()"  
 17     def index(self):  
 18         return "do index()"  
 19     def update(self):  
 20         return "do update()"  
 21     def delete(self):  
 22         return "do delete()"  
 23     def create(self):  
 24         return "do create()"  
 25     def create_many(self):  
 26         return "do create_many()"  
 27     def update_many(self):  
 28         return "do update_many()"  
 29     def list_many(self):  
 30         return "do list_many()"  
 31     def delete_many(self):  
 32         return "do delete_many()"  
 33 
 34 class appclass(object):
 35     def __init__(self):
 36         a = controller()
 37         map = Mapper()
 38         """路由匹配条件1"""  
 39         #curl -X GET http://localhost:8088/images
 40         #匹配条件指定了curl的动作为GET ,访问路径为images  对应的action 为search
 41 
 42         #map.connect('/images',controller=a,  
 43         #           action='search',  
 44         #           conditions={'method':['GET']})  
 45 
 46         """路由匹配条件2"""  
 47         #curl -X GET http://localhost:8088/show/hihi
 48         #curl -X POST http://lcoalhost:8088/failfunc/test
 49         #匹配条件没有指定curl的动作,即action参数,
 50         #因此所有的动作(PUT, POST, GET, ...)都匹配
 51         #第二个curl请求,匹配的action为failfunc, pid为test;但是
 52         #没有定义failfunc函数,报错
 53         #map.connect('name',"/{action}/{pid}",controller=a)  
 54 
 55         """路由匹配条件3"""  
 56         #map.resource内部定义了默认的匹配条件
 57         #第一个参数message为 member_name(资源名),
 58         #第二个参数messages为collection_name(资源集合名),一般定义资源集合名为资源名的复数,我这里随便取名
 59         #collection_name作为访问的路径名,且当没有传入参数controller时,controller=collection_name
 60         #该匹配相当于:
 61         #   map.connect('/messages',controller=a,action='index',conditions={'method':['GET']})
 62         #   map.connect('/messages',controller=a,action='create',conditions={'method':['POST']})
 63         #   map.connect('/messages/{id}',controller=a,action='show',conditions={'method':['GET']})
 64         #   map.connect('/messages/{id}',controller=a,action='update',conditions={'method':['PUT']})
 65         #   map.connect('/messages/{id}',controller=a,action='delete',conditions={'method':['DELETE']})
 66         #前两条是针对整个资源集合的操作,后三条是针对资源集合中某个固定资源的操作
 67 
 68         #map.resource("message","messages",controller=a,collection={'search':'GET'})  
 69 
 70         """路由匹配条件4"""  
 71         """
 72             map.resource除了默认的路由条件外,还可以额外的 '定义资源集合的方法',以及'单个资源的方法'
 73             collection={'search':'GET','create_many':'POST'} 定义了资源集合方法 search,
 74                 其curl动作为GET,create_many,其curl动作为POST
 75             member={'update_many':'POST','delete_many':'POST'} 定义了单个资源方法update_many,
 76                 其curl动作为POST, 其curl动作为POST
 77         """
 78         #map.resource('message', 'messages',controller=a,  
 79                         #collection={'list_many':'GET','create_many':'POST'},  
 80                         #member={'update_many':'POST','delete_many':'POST'})  
 81 
 82         """路由匹配条件5"""  
 83         """
 84             map.resource初始化时还可以指定curl访问路径的前缀路径,如匹配条件3及4没有指定时,默认为
 85             collection_name(资源集合名)
 86         """
 87         map.resource('message', 'messages',controller=a,path_prefix='/{projectid}',  
 88                     collection={'list_many':'GET','create_many':'POST'},  
 89                     member={'update_many':'POST','delete_many':'POST'})  
 90         self.route = middleware.RoutesMiddleware(self.dispatch,map)  
 91     @webob.dec.wsgify  
 92     def __call__(self,req):  
 93         return self.route  
 94  
 95     @staticmethod  
 96     @webob.dec.wsgify  
 97     def dispatch(req):  
 98         match = req.environ['wsgiorg.routing_args'][1]  
 99         print "route match result is:",match  
100         if not match:  
101             return "fake url"  
102   
103         controller = match['controller']  
104         action = match['action']  
105         if hasattr(controller,action):  
106             func = getattr(controller,action)  
107             ret = func()  
108             return ret  
109         else:  
110             return "has no action:%s" %action  
111   
112   
113 if __name__=="__main__":  
114     app = appclass()  
115     server = make_server('',8088,app)  
116     server.serve_forever()

分析:

  1)webob.dec.wsgify是webob为WSGI应用程序提供的一个装饰器,作用是将一个函数转换成一个WSGI应用。
    参考资料 http://tumblr.wachang.NET/post/38149417931/Python-paste-webob-3

  2)routes.middleware.RoutesMiddleware,将接受到的url,自动调用map.match()方法,将url进行路由匹配并将结果存入request请求的环境变量['wsgiorg.routing_args'],最后会调用其第一个参数给出的函数接口,即self.dispatch。

    参考资料   http://blog.csdn.Net/networm3/article/details/8666150

  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 路由匹配结果 (程序中的route match result is) curl请求得到的结果
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']})

    前两条是针对整个资源集合的操作,后三条是针对资源集合中某个固定资源的操作 

  这里匹配结果中的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

  匹配条件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

    在路由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,原因不明,有待研究

相关文章
|
7天前
|
存储 数据挖掘 API
购物平台数据抓取实战指南:从API到深度分析
本指南介绍如何通过API接口抓取淘宝、京东、拼多多等电商平台的数据,涵盖API选择、注册配置、数据抓取与处理、深度分析等内容,帮助企业和开发者挖掘数据价值,支持市场分析和决策制定。
|
10天前
|
安全 API 数据安全/隐私保护
商品详情API接口的优势分析与应用价值
在数字化时代,商品详情API接口为商家和开发者提供了实时更新、高效集成、丰富功能、安全稳定、易于扩展及提升用户体验的解决方案,助力提高运营效率、降低成本并增强市场竞争力。
|
23天前
|
JSON JavaScript API
(API接口系列)商品详情数据封装接口json数据格式分析
在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦!
|
6月前
|
存储 数据可视化 API
1688商品详情数据接口:如何通过1688 API实现批量商品数据抓取和分析
使用1688 API进行批量商品数据抓取和分析,首先需注册账号创建应用获取App Key和Secret Key。研究API文档,构建请求URL,如商品详情、搜索、销售量等接口。利用编程语言发送HTTP请求,实时抓取并处理数据,存储到数据库。实施优化策略,处理错误,记录日志。数据可视化展示并确保API安全性。编写文档并持续更新以适应API变化。参考[c0b.cc/R4rbK2]获取API测试和SDK。
|
26天前
|
API 数据安全/隐私保护 开发者
淘宝 API:关键词搜商品列表接口,助力商家按价格销量排序分析数据
此接口用于通过关键词搜索淘宝商品列表。首先需在淘宝开放平台注册并创建应用获取API权限,之后利用应用密钥和访问令牌调用接口。请求参数包括关键词、页码、每页数量、排序方式及价格区间等。返回结果含总商品数量及具体商品详情。使用时需注意签名验证及官方文档更新。
|
3月前
|
存储 JavaScript 前端开发
探索React状态管理:Redux的严格与功能、MobX的简洁与直观、Context API的原生与易用——详细对比及应用案例分析
【8月更文挑战第31天】在React开发中,状态管理对于构建大型应用至关重要。本文将探讨三种主流状态管理方案:Redux、MobX和Context API。Redux采用单一存储模型,提供预测性状态更新;MobX利用装饰器语法,使状态修改更直观;Context API则允许跨组件状态共享,无需第三方库。每种方案各具特色,适用于不同场景,选择合适的工具能让React应用更加高效有序。
67 0
|
3月前
|
存储 Linux API
Linux源码阅读笔记08-进程调度API系统调用案例分析
Linux源码阅读笔记08-进程调度API系统调用案例分析
|
3月前
|
监控 API 数据安全/隐私保护
​邮件API触发式接口分析?邮件API接口好评榜
邮件API在企业通信和营销中至关重要,通过自动化邮件发送流程提升效率与客户满意度。本文解析邮件API触发式接口,即基于特定事件(如用户注册、购买产品)自动发送邮件的技术,能显著加快企业响应速度并增强用户体验。推荐市场上的优秀邮件API产品,包括SendGrid、Mailgun、Amazon SES、Postmark及新兴的AOKSend,它们各具特色,如高发送率、详细分析工具、灵活配置、强大的日志功能及用户友好的API接口,帮助企业根据不同需求选择最合适的邮件API解决方案。
|
4月前
|
JSON API 网络架构
gRPC 与 REST 的比较分析:哪种 API 适合您的开发需求?
gRPC, 由 Google 推出的开源远程过程调用(RPC)框架, 使两个应用程序间的方法调用变得简单,支持结构化数据的交换。通过采用 Protocol Buffers (Protobuf) ——一种与语言无关的接口定义语言,gRPC 体现了许多现代网络通信技术的优势
gRPC 与 REST 的比较分析:哪种 API 适合您的开发需求?
|
3月前
|
UED 开发工具 iOS开发
Uno Platform大揭秘:如何在你的跨平台应用中,巧妙融入第三方库与服务,一键解锁无限可能,让应用功能飙升,用户体验爆棚!
【8月更文挑战第31天】Uno Platform 让开发者能用同一代码库打造 Windows、iOS、Android、macOS 甚至 Web 的多彩应用。本文介绍如何在 Uno Platform 中集成第三方库和服务,如 Mapbox 或 Google Maps 的 .NET SDK,以增强应用功能并提升用户体验。通过 NuGet 安装所需库,并在 XAML 页面中添加相应控件,即可实现地图等功能。尽管 Uno 平台减少了平台差异,但仍需关注版本兼容性和性能问题,确保应用在多平台上表现一致。掌握正确方法,让跨平台应用更出色。
45 0