moksha/config/middleware.py | 9 ++- moksha/middleware/__init__.py | 3 - moksha/middleware/connector.py | 118 ++++++++++++++++++++++++++++++++++++++++ moksha/middleware/middleware.py | 81 ++------------------------- 4 files changed, 134 insertions(+), 77 deletions(-)
New commits: commit ac33b1149121f5d23427e0b4a309d065e273da46 Merge: 1928722... a816836... Author: John (J5) Palmieri johnp@redhat.com Date: Tue Feb 3 21:27:46 2009 -0500
Merge branch 'master' of git+ssh://johnp@git.fedorahosted.org/git/moksha
commit 192872214440e99545c7dc38566b10f2aa10bdb7 Author: John (J5) Palmieri johnp@redhat.com Date: Tue Feb 3 21:26:44 2009 -0500
split the connector into its own middleware
diff --git a/moksha/config/middleware.py b/moksha/config/middleware.py index b22c418..bfddacf 100644 --- a/moksha/config/middleware.py +++ b/moksha/config/middleware.py @@ -2,7 +2,7 @@
from moksha.config.app_cfg import base_config from moksha.config.environment import load_environment -from moksha.middleware import MokshaMiddleware +from moksha.middleware import MokshaMiddleware, MokshaConnectorMiddleware
# Use base_config to setup the necessary WSGI App factory. # make_base_app will wrap the TG2 app with all the middleware it needs. @@ -10,7 +10,10 @@ make_base_app = base_config.setup_tg_wsgi_app(load_environment)
def make_app(global_conf, full_stack=True, **app_conf): app = make_base_app(global_conf, wrap_app=MokshaMiddleware, - full_stack=True, **app_conf) + full_stack=True, + **app_conf) + + app = MokshaConnectorMiddleware(app)
if base_config.squeeze: from repoze.squeeze.processor import ResourceSqueezingMiddleware @@ -30,4 +33,4 @@ def make_app(global_conf, full_stack=True, **app_conf): path='/__profile__' )
- return app + return app \ No newline at end of file diff --git a/moksha/middleware/__init__.py b/moksha/middleware/__init__.py index 891fe41..40ce721 100644 --- a/moksha/middleware/__init__.py +++ b/moksha/middleware/__init__.py @@ -1,3 +1,4 @@ from middleware import MokshaMiddleware +from connector import MokshaConnectorMiddleware
-__all__ = ('MokshaMiddleware') +__all__ = ('MokshaMiddleware', 'MokshaConnectorMiddleware') diff --git a/moksha/middleware/connector.py b/moksha/middleware/connector.py new file mode 100644 index 0000000..f1f0291 --- /dev/null +++ b/moksha/middleware/connector.py @@ -0,0 +1,118 @@ +# This file is part of Moksha. +# +# Moksha is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Moksha is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Moksha. If not, see http://www.gnu.org/licenses/. +# +# Copyright 2008, Red Hat, Inc. +# Authors: John (J5) Palmieri johnp@redhat.com + +import logging +import pkg_resources +import simplejson as json +import urllib + +from webob import Request, Response +from pylons import config +from pylons.i18n import ugettext + +from moksha.exc import ApplicationNotFound, MokshaException + +log = logging.getLogger(__name__) + +class MokshaConnectorMiddleware(object): + """ + A layer of WSGI middleware that is responsible for handling every + moksha_connector requests. + + If a request for a connector comes in (/moksha_connector/$name), it will + run that connector as defined in it's egg-info. + + """ + def __init__(self, application): + log.info('Creating MokshaConnectorMiddleware') + self.application = application + self.connectors = {} # {'connector name': moksha.IConnector class} + + self.load_connectors() + + def __call__(self, environ, start_response): + + request = Request(environ) + + if request.path.startswith('/moksha_connector'): + s = request.path.split('/')[2:] + + # since keys are not unique we need to condense them + # into an actual dictionary with multiple entries becoming lists + p = request.params + params = {} + for k in p.iterkeys(): + if k == '_cookies': + # reserved parameter + # FIXME: provide a proper error response + return Response(status='404 Not Found') + + if k not in params: + params[k] = p.getall(k) + + response = self._run_connector(s[0], s[1], *s[2:], **params) + else: + response = request.get_response(self.application) + + return response(environ, start_response) + + def _run_connector(self, conn, op, *path, **remote_params): + response = None + # check last part of path to see if it is json data + dispatch_params = {}; + + p = urllib.unquote_plus(path[-1].lstrip()) + if p.startswith('{'): + dispatch_params = json.loads(p) + f = dispatch_params.get('filters') + if isinstance(f, basestring): + dispatch_params['filters'] = json.loads(f) + path = path[:-1] + + # prevent trailing slash + if not p: + path = path[:-1] + + path = '/'.join(path) + conn = self.connectors.get(conn) + + if conn: + conn_obj = conn['connector_class']() + r = conn_obj._dispatch(op, path, remote_params, **dispatch_params) + if not isinstance(r, str): + r = json.dumps(r, separators=(',',':')) + response = Response(r) + else: + response = Response(status='404 Not Found') + + return response + + def load_connectors(self): + log.info('Loading moksha connectors') + for conn_entry in pkg_resources.iter_entry_points('moksha.connector'): + log.info('Loading %s connector' % conn_entry.name) + conn_class = conn_entry.load() + # call the register class method + # FIXME: Should we pass some resource in? + conn_class.register() + conn_path = conn_entry.dist.location + self.connectors[conn_entry.name] = { + 'name': conn_entry.name, + 'connector_class': conn_class, + 'path': conn_path, + } diff --git a/moksha/middleware/middleware.py b/moksha/middleware/middleware.py index 609b806..701f7d5 100644 --- a/moksha/middleware/middleware.py +++ b/moksha/middleware/middleware.py @@ -1,15 +1,15 @@ # This file is part of Moksha. -# +# # Moksha is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. -# +# # Moksha is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with Moksha. If not, see http://www.gnu.org/licenses/. # @@ -57,12 +57,10 @@ class MokshaMiddleware(object): self.menus = {} # {'menu name': MokshaMenu} self.widgets = {} # {'widget name': tw.api.Widget} self.engines = {} # {'app name': sqlalchemy.engine.base.Engine} - self.connectors = {} # {'connector name': moksha.IConnector class}
self.load_paths() self.load_renderers() self.load_configs() - self.load_connectors() self.load_widgets() self.load_applications() self.load_models() @@ -73,7 +71,7 @@ class MokshaMiddleware(object):
def __call__(self, environ, start_response): environ['paste.registry'].register(moksha.apps, self.apps) - + # environ['paste.registry'].register(moksha._widgets, self.widgets) environ['paste.registry'].register(moksha.feed_cache, self.feed_cache) environ['paste.registry'].register(moksha.menus, self.menus) @@ -87,25 +85,6 @@ class MokshaMiddleware(object): response = request.get_response(self.mokshaapp) except ApplicationNotFound: response = Response(status='404 Not Found') - elif request.path.startswith('/moksha_connector'): - # FIXME: this should be separate middleware so other - # frameworks can use connectors - s = request.path.split('/')[2:] - - # since keys are not unique we need to condense them - # into an actual dictionary with multiple entries becoming lists - p = request.params - params = {} - for k in p.iterkeys(): - if k == '_cookies': - # reserved parameter - # FIXME: provide a proper error response - return Response(status='404 Not Found') - - if k not in params: - params[k] = p.getall(k) - - response = self._run_connector(s[0], s[1], *s[2:], **params) else: response = request.get_response(self.application)
@@ -121,36 +100,7 @@ class MokshaMiddleware(object): 'onmessageframe': defaultdict(list) # {topic: [js_callback,]} })
- def _run_connector(self, conn, op, *path, **remote_params): - response = None - # check last part of path to see if it is json data - dispatch_params = {}; - - p = urllib.unquote_plus(path[-1].lstrip()) - if p.startswith('{'): - dispatch_params = json.loads(p) - f = dispatch_params.get('filters') - if isinstance(f, basestring): - dispatch_params['filters'] = json.loads(f) - path = path[:-1] - - # prevent trailing slash - if not p: - path = path[:-1] - - path = '/'.join(path) - conn = self.connectors.get(conn) - - if conn: - conn_obj = conn['connector_class']() - r = conn_obj._dispatch(op, path, remote_params, **dispatch_params) - if not isinstance(r, str): - r = json.dumps(r, separators=(',',':')) - response = Response(r) - else: - response = Response(status='404 Not Found')
- return response
def load_paths(self): """ Load the names and paths of all moksha applications and widgets. @@ -161,7 +111,7 @@ class MokshaMiddleware(object): """ for app_entry in pkg_resources.iter_entry_points('moksha.application'): if app_entry.name in self.apps: - raise MokshaException('Duplicate application name: %s' % + raise MokshaException('Duplicate application name: %s' % app_entry.name) app_path = app_entry.dist.location self.apps[app_entry.name] = { @@ -170,7 +120,7 @@ class MokshaMiddleware(object): } for widget_entry in pkg_resources.iter_entry_points('moksha.widget'): if widget_entry.name in self.widgets: - raise MokshaException('Duplicate widget name: %s' % + raise MokshaException('Duplicate widget name: %s' % widget_entry.name) widget_path = widget_entry.dist.location self.widgets[widget_entry.name] = { @@ -178,21 +128,6 @@ class MokshaMiddleware(object): 'path': widget_path, }
- def load_connectors(self): - log.info('Loading moksha connectors') - for conn_entry in pkg_resources.iter_entry_points('moksha.connector'): - log.info('Loading %s connector' % conn_entry.name) - conn_class = conn_entry.load() - # call the register class method - # FIXME: Should we pass some resource in? - conn_class.register() - conn_path = conn_entry.dist.location - self.connectors[conn_entry.name] = { - 'name': conn_entry.name, - 'connector_class': conn_class, - 'path': conn_path, - } - def load_applications(self): log.info('Loading moksha applications') for app_entry in pkg_resources.iter_entry_points('moksha.application'): @@ -207,7 +142,7 @@ class MokshaMiddleware(object): } try: model = __import__('%s.model' % app_entry.name, - globals(), locals(), + globals(), locals(), [app_entry.name]) self.apps[app_entry.name]['model'] = model except ImportError: @@ -229,7 +164,7 @@ class MokshaMiddleware(object): 'widget': widget, 'path': widget_path, } - + moksha._widgets = self.widgets
def load_menus(self):
moksha-commits@lists.fedorahosted.org