work on a router that works with wsgi and non-wsgi routing

This commit is contained in:
Michael Gundlach
2010-08-10 18:17:44 -04:00
parent c00ae202b9
commit 049b89babe
3 changed files with 94 additions and 12 deletions
+15 -12
View File
@@ -45,18 +45,20 @@ class API(wsgi.Middleware):
def __init__(self):
super(API, self).__init__(Router(webob.exc.HTTPNotFound()))
def __call__(self, environ, start_response):
@webob.dec.wsgify
def __call__(self, req):
return self.application
context = {}
if "HTTP_X_AUTH_TOKEN" in environ:
if "HTTP_X_AUTH_TOKEN" in req.environ:
context['user'] = manager.AuthManager().get_user_from_access_key(
environ['HTTP_X_AUTH_TOKEN'])
req.environ['HTTP_X_AUTH_TOKEN'])
if context['user']:
context['project'] = manager.AuthManager().get_project(
context['user'].name)
if "user" not in context:
return webob.exc.HTTPForbidden()(environ, start_response)
return webob.exc.HTTPForbidden()
environ['nova.context'] = context
return self.application(environ, start_response)
return self.application
class Router(wsgi.Router):
@@ -64,13 +66,14 @@ class Router(wsgi.Router):
def _build_map(self):
"""Build routing map for authentication and cloud."""
self._connect("/v1.0", controller=AuthenticationAPI())
cloud = CloudServerAPI()
self._connect("/servers", controller=cloud.launch_server,
conditions={"method": ["POST"]})
self._connect("/servers/{server_id}", controller=cloud.delete_server,
conditions={'method': ["DELETE"]})
self._connect("/servers", controller=cloud)
self.map.resource("server", "servers", controller=CloudServerAPI())
#self._connect("/v1.0", controller=AuthenticationAPI())
#cloud = CloudServerAPI()
#self._connect("/servers", controller=cloud.launch_server,
# conditions={"method": ["POST"]})
#self._connect("/servers/{server_id}", controller=cloud.delete_server,
# conditions={'method': ["DELETE"]})
#self._connect("/servers", controller=cloud)
class AuthenticationAPI(wsgi.Application):
+76
View File
@@ -40,6 +40,7 @@ def run_server(application, port):
eventlet.wsgi.server(sock, application)
# TODO(gundlach): I think we should toss this class, now that it has no purpose.
class Application(object):
"""Base WSGI application wrapper. Subclasses need to implement __call__."""
@@ -140,6 +141,81 @@ class ParsedRoutes(Middleware):
app = environ['wsgiorg.routing_args'][1]['controller']
return app(environ, start_response)
class MichaelRouter(object):
"""
My attempt at a routing class. Just override __init__ to call
super, then set up routes in self.map.
"""
def __init__(self):
self.map = routes.Mapper()
self._router = routes.middleware.RoutesMiddleware(self._proceed, self.map)
@webob.dec.wsgify
def __call__(self, req):
"""
Route the incoming request to a controller based on self.map.
If no match, return a 404.
"""
return self._router
@webob.dec.wsgify
def _proceed(self, req):
"""
Called by self._router after matching the incoming request to a route
and putting the information into req.environ.
"""
if req.environ['routes.route'] is None:
return webob.exc.HTTPNotFound()
match = environ['wsgiorg.routing_args'][1]
if match.get('_is_wsgi', False):
wsgiapp = match['controller']
return req.get_response(wsgiapp)
else:
# TODO(gundlach): doubt this is the right way -- and it really
# feels like this code should exist somewhere already on the
# internet
controller, action = match['controller'], match['action']
delete match['controller']
delete match['action']
return _as_response(getattr(controller, action)(**match))
controller = environ['wsgiorg.routing_args'][1]['controller']
self._dispatch(controller)
def _as_response(self, result):
"""
When routing to a non-wsgi controller+action, its result will
be passed here before returning up the WSGI chain to be converted
into a webob.Response
class ApiVersionRouter(MichaelRouter):
def __init__(self):
super(ApiVersionRouter, self).__init__(self)
self.map.connect(None, "/v1.0/{path_info:.*}", controller=RsApiRouter())
self.map.connect(None, "/ec2/{path_info:.*}", controller=Ec2ApiRouter())
class RsApiRouter(MichaelRouter):
def __init__(self):
super(RsApiRouter, self).__init__(self)
self.map.resource("server", "servers", controller=CloudServersServerApi())
self.map.resource("image", "images", controller=CloudServersImageApi())
self.map.resource("flavor", "flavors", controller=CloudServersFlavorApi())
self.map.resource("sharedipgroup", "sharedipgroups",
controller=CloudServersSharedIpGroupApi())
class Ec2ApiRouter(object):
def __getattr__(self, key):
return lambda *x: {'dummy response': 'i am a dummy response'}
CloudServersServerApi = CloudServersImageApi = CloudServersFlavorApi = \
CloudServersSharedIpGroupApi = Ec2ApiRouter
class Router(Middleware): # pylint: disable-msg=R0921
"""Wrapper to help setup routes.middleware.RoutesMiddleware."""
+3
View File
@@ -4,11 +4,14 @@ amqplib==0.6.1
anyjson==0.2.4
boto==2.0b1
carrot==0.10.5
eventlet==0.9.10
lockfile==0.8
python-daemon==1.5.5
python-gflags==1.3
redis==2.0.0
routes==1.12.3
tornado==1.0
webob==0.9.8
wsgiref==0.1.2
zope.interface==3.6.1
mox==0.5.0