1Porting Routes to a WSGI Web Framework 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 4RoutesMiddleware 5---------------- 6 7An application can create a raw mapper object and call its ``.match`` and 8``.generate`` methods. However, WSGI applications probably want to use 9the ``RoutesMiddleware`` as Pylons does:: 10 11 # In myapp/config/middleware.py 12 from routes.middleware import RoutesMiddleware 13 app = RoutesMiddleware(app, map) # ``map`` is a routes.Mapper. 14 15The middleware matches the requested URL and sets the following WSGI 16variables:: 17 18 environ['wsgiorg.routing_args'] = ((url, match)) 19 environ['routes.route'] = route 20 environ['routes.url'] = url 21 22where ``match`` is the routing variables dict, ``route`` is the matched route, 23and ``url`` is a ``URLGenerator`` object. In Pylons, ``match`` is used by the 24dispatcher, and ``url`` is accessible as ``pylons.url``. 25 26The middleware handles redirect routes itself, issuing the appropriate 27redirect. The application is not called in this case. 28 29To debug routes, turn on debug logging for the "routes.middleware" logger. 30 31See the Routes source code for other features which may have been added. 32 33URL Resolution 34-------------- 35 36When the URL is looked up, it should be matched against the Mapper. When 37matching an incoming URL, it is assumed that the URL path is the only string 38being matched. All query args should be stripped before matching:: 39 40 m.connect('/articles/{year}/{month}', controller='blog', action='view', year=None) 41 42 m.match('/articles/2003/10') 43 # {'controller':'blog', 'action':'view', 'year':'2003', 'month':'10'} 44 45Matching a URL will return a dict of the match results, if you'd like to 46differentiate between where the argument came from you can use routematch which 47will return the Route object that has all these details:: 48 49 m.connect('/articles/{year}/{month}', controller='blog', action='view', year=None) 50 51 result = m.routematch('/articles/2003/10') 52 # result is a tuple of the match dict and the Route object 53 54 # result[0] - {'controller':'blog', 'action':'view', 'year':'2003', 'month':'10'} 55 # result[1] - Route object 56 # result[1].defaults - {'controller':'blog', 'action':'view', 'year':None} 57 # result[1].hardcoded - ['controller', 'action'] 58 59Your integration code is then expected to dispatch to a controller and action 60in the dict. How it does this is entirely up to the framework integrator. Your 61integration should also typically provide the web developer a mechanism to 62access the additional dict values. 63 64Request Configuration 65--------------------- 66 67If you intend to support ``url_for()`` and ``redirect_to()``, they depend on a 68singleton object which requires additional configuration. You're better off 69not supporting them at all because they will be deprecated soon. 70``URLGenerator`` is the forward-compatible successor to ``url_for()``. 71``redirect_to()`` is better done in the web framework`as in 72``pylons.controllers.util.redirect_to()``. 73 74``url_for()`` and ``redirect_to()`` need information on the current request, 75and since they can be called from anywhere they don't have direct access to the 76WSGI environment. To remedy this, Routes provides a thread-safe singleton class 77called "request_config", which holds the request information for the current 78thread. You should update this after matching the incoming URL but before 79executing any code that might call the two functions. Here is an example:: 80 81 from routes import request_config 82 83 config = request_config() 84 85 config.mapper = m # Your mapper object 86 config.mapper_dict = result # The dict from m.match for this URL request 87 config.host = hostname # The server hostname 88 config.protocol = port # Protocol used, http, https, etc. 89 config.redirect = redir_func # A redirect function used by your framework, that is 90 # expected to take as the first non-keyword arg a single 91 # full or relative URL 92 93See the docstring for ``request_config`` in routes/__init__.py to make sure 94you've initialized everything necessary. 95