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到内部函数的映射;
二、python route 深入
route 可以从url提取相应的参数,如controller,action或者其它用户自己定义的变量
#routes中的Mapper
#Mapper().connect Mapper().match from routes import Mapper
map = Mapper()
map.connect(None,"error/{action}/{id}",controller="controller_obj") #定义匹配规则
result = map.match('error/myapp/4') #匹配url='error/myapp/4'
#result 匹配结果
{'action': u'myapp', 'controller': u'controller_obj', 'id': u''}
map.connect(None,"/message/:name",controller='my_contro') #除 {} 外,:也可以作为匹配符号
result = map.match('/message/12')
#result 匹配结果
{'controller': u'my_contro', 'name': u''}
openstack中的nova-api分析:
#!/usr/bin/env/python
#coding=utf-8
from routes import Mapper
from routes import middleware
import webob.dec
from wsgiref.simple_server import make_server class controller(object):
def __init__(self):
self.i = 1
def __call__(self):
print self.i
def search(self):
return "do search()"
def show(self):
return "do show()"
def index(self):
return "do index()"
def update(self):
return "do update()"
def delete(self):
return "do delete()"
def create(self):
return "do create()"
def create_many(self):
return "do create_many()"
def update_many(self):
return "do update_many()"
def list_many(self):
return "do list_many()"
def delete_many(self):
return "do delete_many()" class appclass(object):
def __init__(self):
a = controller()
map = Mapper()
"""路由匹配条件1"""
#curl -X GET http://localhost:8088/images
#匹配条件指定了curl的动作为GET ,访问路径为images 对应的action 为search #map.connect('/images',controller=a,
# action='search',
# conditions={'method':['GET']}) """路由匹配条件2"""
#curl -X GET http://localhost:8088/show/hihi
#curl -X POST http://lcoalhost:8088/failfunc/test
#匹配条件没有指定curl的动作,即action参数,
#因此所有的动作(PUT, POST, GET, ...)都匹配
#第二个curl请求,匹配的action为failfunc, pid为test;但是
#没有定义failfunc函数,报错
#map.connect('name',"/{action}/{pid}",controller=a) """路由匹配条件3"""
#map.resource内部定义了默认的匹配条件
#第一个参数message为 member_name(资源名),
#第二个参数messages为collection_name(资源集合名),一般定义资源集合名为资源名的复数,我这里随便取名
#collection_name作为访问的路径名,且当没有传入参数controller时,controller=collection_name
#该匹配相当于:
# 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']})
#前两条是针对整个资源集合的操作,后三条是针对资源集合中某个固定资源的操作 #map.resource("message","messages",controller=a,collection={'search':'GET'}) """路由匹配条件4"""
"""
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, 其curl动作为POST
"""
#map.resource('message', 'messages',controller=a,
#collection={'list_many':'GET','create_many':'POST'},
#member={'update_many':'POST','delete_many':'POST'}) """路由匹配条件5"""
"""
map.resource初始化时还可以指定curl访问路径的前缀路径,如匹配条件3及4没有指定时,默认为
collection_name(资源集合名)
"""
map.resource('message', 'messages',controller=a,path_prefix='/{projectid}',
collection={'list_many':'GET','create_many':'POST'},
member={'update_many':'POST','delete_many':'POST'})
self.route = middleware.RoutesMiddleware(self.dispatch,map)
@webob.dec.wsgify
def __call__(self,req):
return self.route @staticmethod
@webob.dec.wsgify
def dispatch(req):
match = req.environ['wsgiorg.routing_args'][1]
print "route match result is:",match
if not match:
return "fake url" controller = match['controller']
action = match['action']
if hasattr(controller,action):
func = getattr(controller,action)
ret = func()
return ret
else:
return "has no action:%s" %action if __name__=="__main__":
app = appclass()
server = make_server('',8088,app)
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,原因不明,有待研究
openstack XXX-api分析的更多相关文章
- OpenStack REST API使用
以前一直想写博客,但因各种因素一直没写.最近在做OpenStack,而OpenStack对外提供REST API,今天就简要介绍一下OpenStack REST API 使用,关于什么是REST AP ...
- 生成的API分析文件太大。我们无法在交付前验证您的API使用信息。这只是通知信息。
这次使用了APICloud平台来开发移动APP, 发布的时候在api控制台云编译成ipa后,这次使用apple提供的Application Loader工具提交apa文件到iTunes上去,提交结束的 ...
- Openstack python api 学习文档 api创建虚拟机
Openstack python api 学习文档 转载请注明http://www.cnblogs.com/juandx/p/4953191.html 因为需要学习使用api接口调用openstack ...
- python调用openstack的api,create_instance的程序解析
python调用openstack的api,create_instance的程序解析 2017年10月17日 15:27:24 CloudXli 阅读数:848 版权声明:本文为博主原创文章,未经 ...
- FFmpeg 学习(四):FFmpeg API 介绍与通用 API 分析
一.FFmpeg 相关术语 1. 容器/文件(Container/File):即特定格式的多媒体文件,比如MP4,flv,mov等. 2. 媒体流(Stream):表示在时间轴上的一段连续的数据,比如 ...
- FFmpeg 学习(五):FFmpeg 编解码 API 分析
在上一篇文章 FFmpeg学习(四):FFmpeg API 介绍与通用 API 分析 中,我们简单的讲解了一下FFmpeg 的API基本概念,并分析了一下通用API,本文我们将分析 FFmpeg 在编 ...
- Azure 认知服务 (3) 计算机视觉API - 分析图像,使用C#代码
<Windows Azure Platform 系列文章目录> 在上一节中Azure 认知服务 (2) 计算机视觉API - 分析图像,笔者介绍了如何使用API测试控制台进行调试. 本章将 ...
- (弃)解读Openstack Identity API v2.0
目前OpenStack社区提供了详尽的API文档,并配有丰富的说明和示例,关于Identity API v2查看这里, 关于Identity API v3请查看这里. 尽管现在官方已经不建议OpenS ...
- 知乎日报 API 分析
声明 下面全部 API 均由 知乎(Zhihu.Inc) 提供,本人採取非正常手段获取. 获取与共享之行为或有侵犯知乎权益的嫌疑.若被告知需停止共享与使用.本人会及时删除此页面与整个项目. 请您暸解相 ...
- 使用curl调试openstack的api
一 系统环境 OpenStack: Mitaka 工具: 最简单的工具:restclient,本次使用curl 二 开搞 访问openstack的API之前,用户使用用户名和密码向keystone进行 ...
随机推荐
- Spring中的代理模式
代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 代理模式是一种 ...
- 启动项目时出现Not a JAR.......Find JAR........一指循环就是起不来
出现问题原因就是mapper的映射文件有问题,里面的返回类型如是实体找不到或者找重复的就会这样 解决办法就是:确保在用的实体(路径)能找到,切记不能有重名的实体
- ASP入门(二十二)-连接数据库
ADO 简介 在 ASP 中访问数据库使用的 ADO 组件. ADO 是一项微软的技术. ADO 指 ActiveX 数据对象(ActiveX Data Objects). ADO 是微软的 Acti ...
- Android 自定义 ListView 显示网络上 JSON 格式歌曲列表
本文内容 环境 项目结构 演示自定义 ListView 显示网络上 JSON 歌曲列表 参考资料 本文最开始看的是一个国人翻译的文章,没有源代码可下载,根据文中提供的代码片段,自己新建的项目(比较可恶 ...
- iOS 获取APP相关信息 私有API
/* Generated by RuntimeBrowser Image: /System/Library/Frameworks/MobileCoreServices.framework/Mobile ...
- linux测试工程介绍(Linux Test Project)
http://ltp.sourceforge.net/ Linux Test Project, 后台很硬,由SGI™ 发起, IBM维护,所以质量有保障. 里面介绍了很多工具,对于一般的基准测试应该是 ...
- Dockerfile 指令 ADD 和 COPY介绍
一.ADD指令 ADD指令的功能是将主机构建环境(上下文)目录中的文件和目录.以及一个URL标记的文件 拷贝到镜像中. 其格式是: ADD 源路径 目标路径 如: #test FROM ubunt ...
- Centos7中安装Python3
环境:CentOS 7 1. 安装依赖环境 # yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-dev ...
- 关于LINUX在中断(硬软)中不能睡眠的真正原因
摘自http://bbs.chinaunix.net/thread-2115820-1-1.html 4楼的回答 先把中断处理流程给出来 1.进入中断处理程序--->2.保存关键上下文----& ...
- Cocos开发小游戏如何实现微信排行榜
当游戏开发进入尾声,要引入微信数据的时候,需要了解和微信相关的接口了. 关系数据链 开放数据域 相关接口如下: wx.getFriendCloudStorage() 获取当前用户也玩该小游戏的好友的用 ...