您的位置:首页 > 其它

简单的 Nova REST API 实现程序

2014-08-22 18:27 344 查看
正在看Nova API的代码, 仿照其中的REST 实现写了一个程序.

Nova API 当然支持了更多的功能, 例如XML/JSON序列化, 身份验证等等. 这个测试程序只实现其中的REST功能

MyRouter: 负责把HTTP请求, 根据匹配规则, 分发到不同的Application中

1) [ Python Deploy ] 收到HTTP请求后, 先调用 MyRouter的 __call__方法进行处理

2) [ MyRouter ] 根据内部的匹配定义, 通过RouteMiddleware 分发到对应的 MyApplication

MyApplication: 收到HTTP 请求后, 解析其中的参数信息, 调用后台的MyController业务类的对应方法

MyController: 最终的业务类, 接受参数, 执行业务逻辑的操作.

from __future__ import print_function
from routes import Mapper
import webob.dec
import webob.exc
import routes.middleware
import testtools

class MyController(object):
def getlist(self, mykey):
print("step 4: MyController's getlist(self, mykey) is invoked")
return "getlist(), mykey=" + mykey

class MyApplication(object):
"""Test application to call from router."""

def __init__(self, controller):
self._controller = controller

def __call__(self, environ, start_response):
print("step 3: MyApplication is invoked")

action_args = environ['wsgiorg.routing_args'][1].copy()
try:
del action_args['controller']
except KeyError:
pass

try:
del action_args['format']
except KeyError:
pass

action = action_args.pop('action', None)
controller_method = getattr(self._controller, action)
result = controller_method(**action_args)

start_response('200 OK', [('Content-Type', 'text/plain')])
return [result]

class MyRouter(object):
"""Test router."""

def __init__(self):
route_name = "dummy_route"
route_path = "/dummies"

my_application = MyApplication(MyController())

self.mapper = Mapper()
self.mapper.connect(route_name, route_path,
controller=my_application,
action="getlist",
mykey="myvalue",
conditions={"method": ['GET']})

self._router = routes.middleware.RoutesMiddleware(self._dispatch,
self.mapper)

@webob.dec.wsgify(RequestClass=webob.Request)
def __call__(self, req):
"""Route the incoming request to a controller based on self.map.

If no match, return a 404.

"""
print("step 1: MyRouter is invoked")
return self._router

@staticmethod
@webob.dec.wsgify(RequestClass=webob.Request)
def _dispatch(req):
"""Dispatch the request to the appropriate controller.

Called by self._router after matching the incoming request to a route
and putting the information into req.environ.  Either returns 404
or the routed WSGI app's response.

"""
print("step 2: RoutesMiddleware is invoked, calling our _dispatch back")

match_dict = req.environ['wsgiorg.routing_args'][1]
if not match_dict:
return webob.exc.HTTPNotFound()
app = match_dict['controller']
return app

class RoutingTestCase(testtools.TestCase):

def test_router(self):
router = MyRouter()
result = webob.Request.blank('/dummies').get_response(router)
self.assertEqual(result.body, "getlist(), mykey=myvalue")


从输出结果, 可以看出调用顺序是: MyRouter --> routes.middleware.RoutesMiddleware --> MyApplication --> MyController:

[Test Case] test_router
step 1: MyRouter is invoked
step 2: RoutesMiddleware is invoked, calling our _dispatch back
step 3: MyApplication is invoked
step 4: MyController's getlist(self, mykey) is invoked
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: