首页 > 代码库 > 简单的类 Nova REST API 实现程序

简单的类 Nova REST API 实现程序

正在看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


简单的类 Nova REST API 实现程序