diff options
author | bbangert <none@none> | 2006-11-07 17:04:22 -0800 |
---|---|---|
committer | bbangert <none@none> | 2006-11-07 17:04:22 -0800 |
commit | 787c16cb10826f3a7951a6195422cf129a5037ef (patch) | |
tree | f8f6a3a138ed79f8c8531b467c1da60b158d7f50 | |
parent | e6253c47450b956050c655c95566d5bd15ead1ac (diff) | |
download | routes-787c16cb10826f3a7951a6195422cf129a5037ef.tar.gz |
[svn] Initial commit of wsgi middleware using routes and new wsgiorg.routing_args spec.
--HG--
branch : trunk
-rw-r--r-- | CHANGELOG | 4 | ||||
-rw-r--r-- | routes/middleware.py | 80 | ||||
-rw-r--r-- | setup.py | 2 |
3 files changed, 84 insertions, 2 deletions
@@ -1,7 +1,9 @@ Routes Changelog ======================== --- 1.5.3 (**svn**) +-- 1.6 (**svn**) +* Added WSGI middleware that does route resolving using new `WSGI.org Routing + Vars Spec <http://wsgi.org/wsgi/Specifications/routing_args>`_. * Added _absolute keyword option route connect to ignore SCRIPT_NAME settings. Suggested by Ian Bicking. diff --git a/routes/middleware.py b/routes/middleware.py new file mode 100644 index 0000000..96292b7 --- /dev/null +++ b/routes/middleware.py @@ -0,0 +1,80 @@ +"""Routes WSGI Middleware""" +import re +import urllib + +try: + from paste.wsgiwrappers import WSGIRequest +except: + pass + +from routes.base import request_config + +class RoutesMiddleware(object): + def __init__(self, wsgi_app, mapper, use_method_override=True, + path_info=True): + """Create a Route middleware object + + Using the use_method_override keyword will require Paste to be + installed, and your application should use Paste's WSGIRequest object + as it will properly handle POST issues with wsgi.input should Routes + check it. + + If path_info is True, then should a route var contain path_info, the + SCRIPT_NAME and PATH_INFO will be altered accordingly. This should be + used with routes like: + + .. code-block:: Python + + map.connect('blog/*path_info', controller='blog', path_info='') + """ + self.app = wsgi_app + self.mapper = mapper + self.use_method_override = use_method_override + self.path_info = path_info + + def __call__(self, environ, start_response): + config = request_config() + config.mapper = self.mapper + + old_method = None + if self.use_method_override: + req = WSGIRequest(environ) + if '_method' in environ.get('QUERY_STRING', '') and '_method' in req.GET: + old_method = environ['REQUEST_METHOD'] + environ['REQUEST_METHOD'] = req.GET['_method'] + elif environ['REQUEST_METHOD'] == 'POST' and '_method' in req.POST: + old_method = environ['REQUEST_METHOD'] + environ['REQUEST_METHOD'] = req.POST['_method'] + + config.environ = environ + match = config.mapper_dict + + if old_method: + environ['REQUEST_METHOD'] = old_method + + if not match: + return self.not_found(environ, start_response) + + for k,v in match.iteritems(): + if v: + match[k] = urllib.unquote_plus(v) + + environ['wsgiorg.routing_args'] = ((), match) + + # If the route included a path_info attribute and it should be used to + # alter the environ, we'll pull it out + if self.path_info and match.get('path_info'): + oldpath = environ['PATH_INFO'] + newpath = match.get('path_info') or '' + environ['PATH_INFO'] = newpath + if not environ['PATH_INFO'].startswith('/'): + environ['PATH_INFO'] = '/' + environ['PATH_INFO'] + environ['SCRIPT_NAME'] += re.sub(r'^(.*?)/' + newpath + '$', r'\1', oldpath) + if environ['SCRIPT_NAME'].endswith('/'): + environ['SCRIPT_NAME'] = environ['SCRIPT_NAME'][:-1] + + return self.app(environ, start_response) + + def not_found(self, environ, start_response): + start_response('404 Not Found', [('Content-type', 'text/plain')]) + return ['Not found'] @@ -3,7 +3,7 @@ use_setuptools() from setuptools import setup, find_packages setup(name="Routes", - version='1.5.3', + version='1.6', description='Routing Recognition and Generation Tools', long_description=""" A Routing package for Python that matches URL's to dicts and vice versa |