<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Groovie: Category Routes</title>
    <link>http://groovie.org/articles/category/routes</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Code, Thoughts, and Misc Debris</description>
    <item>
      <title>Routes planning and the road to Routes 2.0</title>
      <description>&lt;p&gt;&lt;a href="http://routes.groovie.org/"&gt;Routes&lt;/a&gt; has been a wonderfully successful project of mine as its used not just in &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt; but quite a few other small &lt;span class="caps"&gt;WSGI&lt;/span&gt; apps. It&amp;#8217;s even been &lt;a href="http://www.aminus.org/blogs/index.php/fumanchu/2006/10/14/if_you_like_cherrypy_except_for_the_disp"&gt;integrated as a CherryPy &lt;span class="caps"&gt;URL&lt;/span&gt; dispatching option&lt;/a&gt; for those using TurboGears 1.x or plain CherryPy. It&amp;#8217;s come a long way since 1.0 and has diverged on quite a few fronts from the Rails version that it was originally duplicating in functionality, which has me thinking that perhaps its time to consider 2.0 and what that will mean.&lt;/p&gt;


	&lt;p&gt;First, I think there&amp;#8217;s quite a few behaviors that don&amp;#8217;t make sense and probably never have. The &lt;a href="http://routes.groovie.org/manual.html#minimum-urls"&gt;Route minimizing functionality&lt;/a&gt; sounds neat and fulfills the Rails ideal of &amp;#8216;keeping urls pretty&amp;#8217; yet suffers from a fundamental flaw&amp;#8230; they result in &lt;a href="http://jtauber.com/blog/2007/08/22/trailing_slashes/"&gt;multiple valid &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s for the same page&lt;/a&gt;. James Tauber covers some of the implications of this in addition to the issue with relative &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s not working right either. The example he cites is even worse for Routes since Routes can easily result in multiple &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s mapping to the same controller action.&lt;/p&gt;


	&lt;h2&gt;Routes 2.0&lt;/h2&gt;


	&lt;p&gt;To solve the multiple &lt;span class="caps"&gt;URL&lt;/span&gt; issue, and also address some Named Routes confusion that recently hit the Pylons mailing list, Routes 2.0 will do a few things differently than Routes 1.X. Many things will be significantly more explicit and more predictable as a result. In addition, I want to add more functionality so that Routes can be the end-all of &lt;span class="caps"&gt;URL&lt;/span&gt; generation in addition to &lt;span class="caps"&gt;URL&lt;/span&gt; dispatching, even for use purely generating links conditionally that aren&amp;#8217;t even used for &lt;span class="caps"&gt;URL&lt;/span&gt; dispatching.&lt;/p&gt;


	&lt;p&gt;Some of the key changes planned for Routes 2.0:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Routes recognition and generation will always be explicit&lt;/b&gt;
  Currently, there&amp;#8217;s an explicit option that removes the keyword controller/action/id defaults, 2.0 will not have these implicit defaults.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Defaults don&amp;#8217;t cause minimization&lt;/b&gt;
  Defaults just mean they&amp;#8217;ll be used, they won&amp;#8217;t result in Route minimization which increases the amount of &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s that end up matching to a single controller action.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Trailing slashes shouldn&amp;#8217;t be an issue&lt;/b&gt;
  Without routes being minimized, a route such as &amp;#8217;/home/index&amp;#8217; will always be &amp;#8217;/home/index&amp;#8217; instead of being minimized to /home/. This will resolve the trailing slash issue.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Named Routes will always use the route named&lt;/b&gt;
  A named route currently just means that the defaults for that route will be used during route generation. This currently can cause confusion because people believe that the named route actually forces that route to be used during generation.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Generation-only routes&lt;/b&gt;
  A new option, which will result in routes that are used purely for generation. This option will likely be used primarily for static resources which may be on other servers, or may need the domain rotated so that the browser can do parallel resource loading. For example, one would be able to provide a list of domains to be used, and the generated links will rotate as desired on the page to split page resources over multiple domains.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Redirect routes&lt;/b&gt;
  Sometimes, (especially when replacing legacy apps), its desirable to slowly migrate &lt;span class="caps"&gt;URL&lt;/span&gt; scheme&amp;#8217;s from the old to the new rather. While &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s &lt;a href="http://www.w3.org/Provider/Style/URI"&gt;should never change&lt;/a&gt;, sometimes the system being replaced has horrid &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s that violate all &lt;span class="caps"&gt;URL&lt;/span&gt; recommendations. Being able to provide a smooth migration path from the old &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s to the new ones is handy, and permanent redirects are respected by many search crawlers as well.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Migration and Compatibility&lt;/h2&gt;


	&lt;p&gt;Routes 1.8 will include options to turn on behavior that will be the default in Routes 2.0, and if you like how Routes 1.X works there&amp;#8217;s no need to worry, it will still be maintained for the foreseeable future. It&amp;#8217;s currently extremely stable, and has a massive unit test suite to ensure it operates as designed.&lt;/p&gt;


	&lt;h2&gt;Add Your Desired Feature Here&lt;/h2&gt;


	&lt;p&gt;What other features are Routes users currently looking for?&lt;/p&gt;</description>
      <pubDate>Wed, 29 Aug 2007 10:04:24 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:70c0b36f-4959-4c67-a721-200da42574e0</guid>
      <author>ben</author>
      <link>http://groovie.org/articles/2007/08/29/routes-planning-and-the-road-to-routes-2-0</link>
      <category>Python</category>
      <category>Routes</category>
    </item>
    <item>
      <title>Routes planning and the road to Routes 2.0</title>
      <description>&lt;p&gt;&lt;a href="http://routes.groovie.org/"&gt;Routes&lt;/a&gt; has been a wonderfully successful project of mine as its used not just in &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt; but quite a few other small &lt;span class="caps"&gt;WSGI&lt;/span&gt; apps. It&amp;#8217;s even been &lt;a href="http://www.aminus.org/blogs/index.php/fumanchu/2006/10/14/if_you_like_cherrypy_except_for_the_disp"&gt;integrated as a CherryPy &lt;span class="caps"&gt;URL&lt;/span&gt; dispatching option&lt;/a&gt; for those using TurboGears 1.x or plain CherryPy. It&amp;#8217;s come a long way since 1.0 and has diverged on quite a few fronts from the Rails version that it was originally duplicating in functionality, which has me thinking that perhaps its time to consider 2.0 and what that will mean.&lt;/p&gt;


	&lt;p&gt;First, I think there&amp;#8217;s quite a few behaviors that don&amp;#8217;t make sense and probably never have. The &lt;a href="http://routes.groovie.org/manual.html#minimum-urls"&gt;Route minimizing functionality&lt;/a&gt; sounds neat and fulfills the Rails ideal of &amp;#8216;keeping urls pretty&amp;#8217; yet suffers from a fundamental flaw&amp;#8230; they result in &lt;a href="http://jtauber.com/blog/2007/08/22/trailing_slashes/"&gt;multiple valid &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s for the same page&lt;/a&gt;. James Tauber covers some of the implications of this in addition to the issue with relative &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s not working right either. The example he cites is even worse for Routes since Routes can easily result in multiple &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s mapping to the same controller action.&lt;/p&gt;


	&lt;h2&gt;Routes 2.0&lt;/h2&gt;


	&lt;p&gt;To solve the multiple &lt;span class="caps"&gt;URL&lt;/span&gt; issue, and also address some Named Routes confusion that recently hit the Pylons mailing list, Routes 2.0 will do a few things differently than Routes 1.X. Many things will be significantly more explicit and more predictable as a result. In addition, I want to add more functionality so that Routes can be the end-all of &lt;span class="caps"&gt;URL&lt;/span&gt; generation in addition to &lt;span class="caps"&gt;URL&lt;/span&gt; dispatching, even for use purely generating links conditionally that aren&amp;#8217;t even used for &lt;span class="caps"&gt;URL&lt;/span&gt; dispatching.&lt;/p&gt;


	&lt;p&gt;Some of the key changes planned for Routes 2.0:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;Routes recognition and generation will always be explicit&lt;/b&gt;
  Currently, there&amp;#8217;s an explicit option that removes the keyword controller/action/id defaults, 2.0 will not have these implicit defaults.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Defaults don&amp;#8217;t cause minimization&lt;/b&gt;
  Defaults just mean they&amp;#8217;ll be used, they won&amp;#8217;t result in Route minimization which increases the amount of &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s that end up matching to a single controller action.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Trailing slashes shouldn&amp;#8217;t be an issue&lt;/b&gt;
  Without routes being minimized, a route such as &amp;#8217;/home/index&amp;#8217; will always be &amp;#8217;/home/index&amp;#8217; instead of being minimized to /home/. This will resolve the trailing slash issue.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Named Routes will always use the route named&lt;/b&gt;
  A named route currently just means that the defaults for that route will be used during route generation. This currently can cause confusion because people believe that the named route actually forces that route to be used during generation.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Generation-only routes&lt;/b&gt;
  A new option, which will result in routes that are used purely for generation. This option will likely be used primarily for static resources which may be on other servers, or may need the domain rotated so that the browser can do parallel resource loading. For example, one would be able to provide a list of domains to be used, and the generated links will rotate as desired on the page to split page resources over multiple domains.&lt;/li&gt;
		&lt;li&gt;&lt;b&gt;Redirect routes&lt;/b&gt;
  Sometimes, (especially when replacing legacy apps), its desirable to slowly migrate &lt;span class="caps"&gt;URL&lt;/span&gt; scheme&amp;#8217;s from the old to the new rather. While &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s &lt;a href="http://www.w3.org/Provider/Style/URI"&gt;should never change&lt;/a&gt;, sometimes the system being replaced has horrid &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s that violate all &lt;span class="caps"&gt;URL&lt;/span&gt; recommendations. Being able to provide a smooth migration path from the old &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s to the new ones is handy, and permanent redirects are respected by many search crawlers as well.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Migration and Compatibility&lt;/h2&gt;


	&lt;p&gt;Routes 1.8 will include options to turn on behavior that will be the default in Routes 2.0, and if you like how Routes 1.X works there&amp;#8217;s no need to worry, it will still be maintained for the foreseeable future. It&amp;#8217;s currently extremely stable, and has a massive unit test suite to ensure it operates as designed.&lt;/p&gt;


	&lt;h2&gt;Add Your Desired Feature Here&lt;/h2&gt;


	&lt;p&gt;What other features are Routes users currently looking for?&lt;/p&gt;</description>
      <pubDate>Wed, 29 Aug 2007 10:04:24 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:70c0b36f-4959-4c67-a721-200da42574e0</guid>
      <author>ben</author>
      <link>http://groovie.org/articles/2007/08/29/routes-planning-and-the-road-to-routes-2-0</link>
      <category>Python</category>
      <category>Routes</category>
    </item>
    <item>
      <title>Routes functional conditions and WSGI Middleware</title>
      <description>&lt;p&gt;Sometimes, it amazes me whats possible fully utilizing &lt;span class="caps"&gt;WSGI&lt;/span&gt; middleware in an application stack. While it likely isn&amp;#8217;t something totally unique to the framework, the relative ease with which it can be done still sometimes gets me to grin.&lt;/p&gt;


	&lt;p&gt;Tonight, a Pylons user on the &lt;span class="caps"&gt;IRC&lt;/span&gt; channel (irc.freenode.net, #pylons) asked if it was possible to get a &lt;span class="caps"&gt;URL&lt;/span&gt; laid out so that /s/SOMETHING would map into their &amp;#8217;s&amp;#8217; controller, with the second part passed in as a variable. That alone is pretty easy, however the additional requirement was that the controller action would change depending on the user&amp;#8217;s &amp;#8220;type&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;There&amp;#8217;s two ways to deal with this, the first of which is the only possible way in many frameworks. Have every request to the &lt;span class="caps"&gt;URL&lt;/span&gt; map to a single function, and in that function load up the session and call the appropriate function to handle the request based on their user type. This way works fine in Pylons too, but thanks to Routes and &lt;span class="caps"&gt;WSGI&lt;/span&gt; middleware we have another option.&lt;/p&gt;


	&lt;p&gt;Routes has a lot of capabilities to it, there&amp;#8217;s been numerous additions to the Python implementation that the Rails version is not capable of. One of them is the ability to alter the resulting &lt;span class="caps"&gt;URL&lt;/span&gt; match dictionary in various conditional functions. To toggle the controller action used, we&amp;#8217;ll be using the ability to &lt;a href="http://routes.groovie.org/manual.html#conditions"&gt;pass in a function to Routes conditions&lt;/a&gt; that can alter the resulting match.&lt;/p&gt;


	&lt;p&gt;This condition checking function has full access to the &lt;a href="http://www.python.org/dev/peps/pep-0333/#environ-variables"&gt;&lt;span class="caps"&gt;WSGI&lt;/span&gt; environ&lt;/a&gt; so if you wanted to restrict a specific controller/action combination to people referred from Slashdot, no problem! You can carefully fine-tune the conditions required for dispatch at the same place you define your &lt;span class="caps"&gt;URL&lt;/span&gt; resolution.&lt;/p&gt;


	&lt;p&gt;Since Pylons uses &lt;a href="http://beaker.groovie.org/"&gt;Beaker&lt;/a&gt; for session handling via &lt;span class="caps"&gt;WSGI&lt;/span&gt; middleware, the session object will already be available when our Pylons app gets called. Beaker loads the user session into &lt;code&gt;environ['beaker.session']&lt;/code&gt;. Given this knowledge, we can write a conditional function for use with Routes like so:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
def check_user(environ, result):
    session = environ['beaker.session']
    user_type = session.get('type')
    if not user_type:
        result['action'] = 'index'
    elif user_type == 'admin':
        result['action'] = 'view_action'
    else:
        result['action'] = 'not_logged_in'
    return True
map.connect('s/:domain', controller='s', conditions=dict(function=check_user))
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Viola! Now Routes will run the function provided to see if it returns &lt;code&gt;True&lt;/code&gt; before accepting that as a valid match. In the process, the action used will be set as desired. I&amp;#8217;ve always thought a good sign something is well designed is when people can use it in ways you didn&amp;#8217;t originally anticipate. If that&amp;#8217;s the criteria, I think Routes succeeds and then some.&lt;/p&gt;


	&lt;p&gt;&lt;b&gt;Disclaimer: Yes, I wrote Routes, and a good chunk of Beaker and Pylons, so I might be biased and tooting my own horn. :)&lt;/b&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 18 Aug 2007 21:38:51 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:c8b988b2-f83b-40de-bae9-53c5f5fb0909</guid>
      <author>ben</author>
      <link>http://groovie.org/articles/2007/08/18/routes-functional-conditions-and-wsgi-middleware</link>
      <category>Python</category>
      <category>Routes</category>
    </item>
    <item>
      <title>Routes functional conditions and WSGI Middleware</title>
      <description>&lt;p&gt;Sometimes, it amazes me whats possible fully utilizing &lt;span class="caps"&gt;WSGI&lt;/span&gt; middleware in an application stack. While it likely isn&amp;#8217;t something totally unique to the framework, the relative ease with which it can be done still sometimes gets me to grin.&lt;/p&gt;


	&lt;p&gt;Tonight, a Pylons user on the &lt;span class="caps"&gt;IRC&lt;/span&gt; channel (irc.freenode.net, #pylons) asked if it was possible to get a &lt;span class="caps"&gt;URL&lt;/span&gt; laid out so that /s/SOMETHING would map into their &amp;#8217;s&amp;#8217; controller, with the second part passed in as a variable. That alone is pretty easy, however the additional requirement was that the controller action would change depending on the user&amp;#8217;s &amp;#8220;type&amp;#8221;.&lt;/p&gt;


	&lt;p&gt;There&amp;#8217;s two ways to deal with this, the first of which is the only possible way in many frameworks. Have every request to the &lt;span class="caps"&gt;URL&lt;/span&gt; map to a single function, and in that function load up the session and call the appropriate function to handle the request based on their user type. This way works fine in Pylons too, but thanks to Routes and &lt;span class="caps"&gt;WSGI&lt;/span&gt; middleware we have another option.&lt;/p&gt;


	&lt;p&gt;Routes has a lot of capabilities to it, there&amp;#8217;s been numerous additions to the Python implementation that the Rails version is not capable of. One of them is the ability to alter the resulting &lt;span class="caps"&gt;URL&lt;/span&gt; match dictionary in various conditional functions. To toggle the controller action used, we&amp;#8217;ll be using the ability to &lt;a href="http://routes.groovie.org/manual.html#conditions"&gt;pass in a function to Routes conditions&lt;/a&gt; that can alter the resulting match.&lt;/p&gt;


	&lt;p&gt;This condition checking function has full access to the &lt;a href="http://www.python.org/dev/peps/pep-0333/#environ-variables"&gt;&lt;span class="caps"&gt;WSGI&lt;/span&gt; environ&lt;/a&gt; so if you wanted to restrict a specific controller/action combination to people referred from Slashdot, no problem! You can carefully fine-tune the conditions required for dispatch at the same place you define your &lt;span class="caps"&gt;URL&lt;/span&gt; resolution.&lt;/p&gt;


	&lt;p&gt;Since Pylons uses &lt;a href="http://beaker.groovie.org/"&gt;Beaker&lt;/a&gt; for session handling via &lt;span class="caps"&gt;WSGI&lt;/span&gt; middleware, the session object will already be available when our Pylons app gets called. Beaker loads the user session into &lt;code&gt;environ['beaker.session']&lt;/code&gt;. Given this knowledge, we can write a conditional function for use with Routes like so:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
def check_user(environ, result):
    session = environ['beaker.session']
    user_type = session.get('type')
    if not user_type:
        result['action'] = 'index'
    elif user_type == 'admin':
        result['action'] = 'view_action'
    else:
        result['action'] = 'not_logged_in'
    return True
map.connect('s/:domain', controller='s', conditions=dict(function=check_user))
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Viola! Now Routes will run the function provided to see if it returns &lt;code&gt;True&lt;/code&gt; before accepting that as a valid match. In the process, the action used will be set as desired. I&amp;#8217;ve always thought a good sign something is well designed is when people can use it in ways you didn&amp;#8217;t originally anticipate. If that&amp;#8217;s the criteria, I think Routes succeeds and then some.&lt;/p&gt;


	&lt;p&gt;&lt;b&gt;Disclaimer: Yes, I wrote Routes, and a good chunk of Beaker and Pylons, so I might be biased and tooting my own horn. :)&lt;/b&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 18 Aug 2007 21:38:51 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:c8b988b2-f83b-40de-bae9-53c5f5fb0909</guid>
      <author>ben</author>
      <link>http://groovie.org/articles/2007/08/18/routes-functional-conditions-and-wsgi-middleware</link>
      <category>Python</category>
      <category>Routes</category>
    </item>
    <item>
      <title>Routes 1.4 Release and Web Services</title>
      <description>&lt;p&gt;This is slightly old as &lt;a href="http://routes.groovie.org/"&gt;Routes&lt;/a&gt; 1.4 was released about a week and a half ago, but I thought it deserved some attention. There were a handful of fixes and some slightly major feature enhancements in 1.4.&lt;/p&gt;


	&lt;p&gt;From the changelog:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Fixed bug with map.resource related to member methods, found in Rails version.&lt;/li&gt;
		&lt;li&gt;Fixed bug with map.resource member methods not requiring a member id.&lt;/li&gt;
		&lt;li&gt;Fixed bug related to handling keyword argument controller.&lt;/li&gt;
		&lt;li&gt;Added map.resource command which can automatically generate a batch of routes
  intended to be used in a &lt;span class="caps"&gt;REST&lt;/span&gt;-ful manner by a web framework.&lt;/li&gt;
		&lt;li&gt;Added &lt;span class="caps"&gt;URL&lt;/span&gt; generation handling for a &amp;#8216;method&amp;#8217; argument. If &amp;#8216;method&amp;#8217; is specified, it
  is not dropped and will be changed to &amp;#8216;_method&amp;#8217; for use by the framework.&lt;/li&gt;
		&lt;li&gt;Added conditions option to map.connect. Accepts a dict with optional keyword args
  &amp;#8216;method&amp;#8217; or &amp;#8216;function&amp;#8217;. Method is a list of &lt;span class="caps"&gt;HTTP&lt;/span&gt; methods that are valid for the route.
  Function is a function that will be called with environ, matchdict where matchdict is
  the dict created by the &lt;span class="caps"&gt;URL&lt;/span&gt; match.&lt;/li&gt;
		&lt;li&gt;Fixed redirect_to function for using absolute &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s. redirect_to now passes all
  args to url_for, then passes the resulting &lt;span class="caps"&gt;URL&lt;/span&gt; to the redirect function. Reported
  by climbus.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h4&gt;Web Resources&lt;/h4&gt;


	&lt;p&gt;The map.resource command is based directly off the &lt;a href="http://plugins.radrails.org/directory/show/69"&gt;Simply Restful&lt;/a&gt; Rails plugin which adds support for various verb-oriented controller actions in a &lt;a href="http://www.xml.com/pub/a/2004/12/01/restful-web.html"&gt;RESTful service&lt;/a&gt; style approach. The Simply Restful layout is more or less the exact service style laid out in the &lt;a href="http://bitworking.org/projects/atom/draft-ietf-atompub-protocol-09.html"&gt;Atom Publishing Protocol&lt;/a&gt;.&lt;/p&gt;


It&amp;#8217;s a great approach and it also meant providing a few other features to Routes that I hadn&amp;#8217;t implemented previously, the most important being able to limit matching of a &lt;span class="caps"&gt;URL&lt;/span&gt; based on the &lt;span class="caps"&gt;HTTP&lt;/span&gt; method used. This is present in the new conditions clause for a Route:
&lt;pre&gt;&lt;code&gt;
map.connect('user/:id', controller='user', action='edit', 
    conditions={'method', ['GET', 'HEAD']})
map.connect('user/:id', controller='user', action='update',
    conditions={'method', ['PUT']})
&lt;/code&gt;&lt;/pre&gt;

The conditions clause can also accept your own function should you want to restrict the route to matching based off some other criteria (sub-domain, IP address, etc).
&lt;pre&gt;&lt;code&gt;
def stop_comcast(environ, match):
    if 'comcast.net' in environ['REMOTE_HOST']:
        return False
    return True

map.connect(':controller/:action/:id', conditions={'function':stop_comcast})
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;&lt;a href="http://loudthinking.com/"&gt;David Heinemeier Hansson&lt;/a&gt; recently posted an &lt;a href="http://www.loudthinking.com/arc/000593.html"&gt;entry about Resources on Rails&lt;/a&gt; discussing how important web services are. The other key point was to make it easier to write controllers that could not only give you easy browser access to your resources, but provide a web service &lt;span class="caps"&gt;API&lt;/span&gt; as well.&lt;/p&gt;


The two snippets shown above give you an &lt;code&gt;edit&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; capability that restricts matching based off the &lt;span class="caps"&gt;HTTP&lt;/span&gt; method (verb). Writing a huge mess of those for the rest of the functions needed for a full web service &lt;span class="caps"&gt;API&lt;/span&gt; like Atom is a bit of busy-body work, so in the opinionated style of Rails a single command wraps up the whole thing. In Routes it looks like this:
&lt;pre&gt;&lt;code&gt;
map.resource('user')
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That will make the two routes at the top of this entry in addition to routes that handle &lt;span class="caps"&gt;PUT&lt;/span&gt;, and &lt;span class="caps"&gt;DELETE&lt;/span&gt;. It maps them out to a set of actions in the controller, and provides the capability to easily add more methods for specific verbs.&lt;/p&gt;


	&lt;p&gt;The &lt;code&gt;map.resource&lt;/code&gt; command is still getting tuned up, and we&amp;#8217;re integrating the additional functionality it provides back into &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt; as well. Josh Triplett also wrote some Python code that will parse &lt;span class="caps"&gt;HTTP&lt;/span&gt; Accept headers fully so that we can add some nice functionality to use in the controller to return the appropriate data given what the client is expecting (HTML, &lt;span class="caps"&gt;XML&lt;/span&gt;, JSON, etc.)&lt;/p&gt;


	&lt;p&gt;If you&amp;#8217;re using a Python web framework that doesn&amp;#8217;t use Routes&amp;#8230; maybe its time to put a request in. :)&lt;/p&gt;</description>
      <pubDate>Wed, 02 Aug 2006 10:26:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:2e4b09e4-489d-4899-b4a5-f283b50d6188</guid>
      <author>ben</author>
      <link>http://groovie.org/articles/2006/08/02/routes-1-4-release-and-web-services</link>
      <category>Code</category>
      <category>Python</category>
      <category>Rails</category>
      <category>Routes</category>
    </item>
    <item>
      <title>Pylons Related News for the 4th of July</title>
      <description>&lt;p&gt;It&amp;#8217;s been a busy month for &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt;, with lots of changes for the big internal &lt;span class="caps"&gt;API&lt;/span&gt; change in 0.9. The great news for those making Pylons apps right now with 0.8.2 is how &lt;strong&gt;few&lt;/strong&gt; backwards compatibility issues there are. Most of the big changes take place under the hood and compatibility objects are present to mitigate the massive breakage that I&amp;#8217;ve seen happen in other framework upgrades.&lt;/p&gt;


	&lt;p&gt;This is going to remain a big focus on future development in Pylons too, and the &lt;span class="caps"&gt;API&lt;/span&gt; in 0.9 is solid enough that I don&amp;#8217;t see anything but minor tweaks in the future (1.0 and beyond). Pylons based apps will be easy to maintain and upgrade thanks primarily to &lt;span class="caps"&gt;WSGI&lt;/span&gt;.&lt;/p&gt;


	&lt;h4&gt;No &lt;a href="http://en.wikipedia.org/wiki/Not_Invented_Here"&gt;&lt;span class="caps"&gt;NIH&lt;/span&gt; Syndrome&lt;/a&gt; Here!&lt;/h4&gt;


	&lt;p&gt;We&amp;#8217;ve taken some cues from the &lt;a href="http://www.djangoproject.com/"&gt;Django project&lt;/a&gt; that we believe make for a cleaner request-cycle. In Pylons 0.9, controllers are expected to return a &lt;code&gt;response&lt;/code&gt; object, and for convenience a method is included that renders a template to a new response object and returns it (This will look very familiar to Djangonauts).&lt;/p&gt;


	&lt;p&gt;The command was integrated with a slightly more enhanced version of &lt;a href="http://projects.dowski.com/projects/buffet"&gt;Buffet&lt;/a&gt; along with the &lt;a href="http://beaker.groovie.org/"&gt;Beaker Session/Caching middleware&lt;/a&gt;. The end-result is a powerful command that not only can render templates in any &lt;a href="http://www.turbogears.org/docs/plugins/template.html"&gt;Template-Plugin compatible&lt;/a&gt; template language, but the rendered result can also be cached. It&amp;#8217;s a great way to utilize template languages which might not be all that quick by themselves.&lt;/p&gt;


Sample controller in Pylons 0.9:
&lt;pre&gt;&lt;code&gt;
from myproj.lib.base import *

class UserController(BaseController):
    def show(self, id):
        # Cache based on id in the URL, for 30 seconds
        return render_response('/user/show.myt', cache_key=id, cache_expire=30)

    def index(self):
        # Just for fun, use Kid to render the index
        return render_response('kid', 'user.index', cache_expire=15)
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Being able to easily cache any template in any template language makes it very easy to sprinkle in caching when you need to handle massive loads yet stay dynamic.&lt;/p&gt;


	&lt;p&gt;Another new feature present in the latest &lt;a href="http://routes.groovie.org/"&gt;Routes&lt;/a&gt; and Pylons is resource mappings, which automatically generate routes for you with &lt;span class="caps"&gt;HTTP&lt;/span&gt; method restrictions. This makes it easy to setup controllers and their actions for specific &lt;span class="caps"&gt;HTTP&lt;/span&gt; verbs (aka, &lt;span class="caps"&gt;REST&lt;/span&gt;-ful &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s and web services). The implementation of this feature was directly inspired by the &lt;a href="http://plugins.radrails.org/directory/show/69"&gt;Simply Restful&lt;/a&gt; Rails plug-in that was also demo&amp;#8217;d by David Hansson in his &lt;a href="http://www.loudthinking.com/arc/000593.html"&gt;Resources on Rails&lt;/a&gt; talk. Being able to &lt;a href="http://groups.google.com/group/pylons-discuss/browse_frm/thread/86f8abc048dd7ce7"&gt;discriminate valid routes based on &lt;span class="caps"&gt;HTTP&lt;/span&gt; method&lt;/a&gt; was brought up in the past and I&amp;#8217;m happy to have seen an implementation that solves the issues I originally had with the idea.&lt;/p&gt;


	&lt;p&gt;The one feature still in development is to easily discern the content type requested, which was also inspired by Rails. Josh Triplett has written some code that deals with the ugly task of parsing the &lt;span class="caps"&gt;HTTP&lt;/span&gt; Accept headers, and I&amp;#8217;m working on adding it into Paste for easy re-use by all. Combined with Routes, it&amp;#8217;ll provide a clean and easy way to setup web applications that can serve multiple forms of content from a single action.&lt;/p&gt;


	&lt;h4&gt;Conferences&lt;/h4&gt;


	&lt;p&gt;Pylons was represented at &lt;a href="http://www.europython.org/"&gt;EuroPython&lt;/a&gt; by the other lead developer of Pylons, James Gardner. For those still trying to grasp &lt;span class="caps"&gt;WSGI&lt;/span&gt;, he gave a &lt;a href="http://indico.cern.ch/materialDisplay.py?contribId=104&amp;amp;sessionId=9&amp;amp;materialId=slides&amp;amp;confId=44"&gt;talk on &lt;span class="caps"&gt;WSGI&lt;/span&gt; and middleware&lt;/a&gt; that looks like it was quite interesting (I wasn&amp;#8217;t there unfortunately.)&lt;/p&gt;


	&lt;p&gt;Other talks involving Pylons at EuroPython:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Dr. Rob Collins gave a &lt;a href="http://indico.cern.ch/contributionDisplay.py?contribId=109&amp;#38;sessionId=50&amp;#38;confId=44"&gt;presentation on Factory monitoring with Pylons, &lt;span class="caps"&gt;XML&lt;/span&gt;-RPC and &lt;span class="caps"&gt;SVG&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;James Gardner&amp;#8217;s &lt;a href="http://indico.cern.ch/contributionDisplay.py?contribId=105&amp;#38;sessionId=9&amp;#38;confId=44"&gt;full talk on Pylons&lt;/a&gt;, and &lt;a href="http://indico.cern.ch/materialDisplay.py?contribId=105&amp;amp;sessionId=9&amp;amp;materialId=slides&amp;amp;confId=44"&gt;slides of his Pylons talk&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Web Framework Shoot-out between Django, Zope, TurboGears, and Pylons (If more were covered, please let me know)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I&amp;#8217;ll be at &lt;a href="http://conferences.oreillynet.com/os2006/"&gt;&lt;span class="caps"&gt;OSCON&lt;/span&gt;&lt;/a&gt; for those interested in chatting about Pylons, Python, or Python web frameworks later this month.&lt;/p&gt;


	&lt;h4&gt;Pylons 0.9 Release&lt;/h4&gt;


	&lt;p&gt;We&amp;#8217;re currently wrapping up new features in 0.9, to make sure the resource mapping capability is present before a feature-freeze for release. Hopefully the release will be out within the next 2 weeks, if you haven&amp;#8217;t checked out Pylons before I&amp;#8217;d highly suggest taking a look at 0.9!&lt;/p&gt;</description>
      <pubDate>Tue, 04 Jul 2006 12:55:33 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:625dad7b-9a2c-4655-ba76-89c162643d69</guid>
      <author>ben</author>
      <link>http://groovie.org/articles/2006/07/04/pylons-related-news-for-the-4th-of-july</link>
      <category>Code</category>
      <category>Python</category>
      <category>Routes</category>
    </item>
    <item>
      <title>Routes 1.3.1</title>
      <description>&lt;p&gt;Ah yes, time for another release. This time its &lt;a href="http://routes.groovie.org/"&gt;Routes&lt;/a&gt; 1.3.1, nothing too big to see here, thus the minor version increase. However if you were using Routes with the &lt;code&gt;prefix&lt;/code&gt; option its highly recommended that you upgrade as there were 2 bugs specifically when used with that option that have been fixed.&lt;/p&gt;


	&lt;p&gt;Also, for those that want all their &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s to end in a &lt;code&gt;/&lt;/code&gt;, there&amp;#8217;s now a append_slash option that will ensure &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s are generated exactly how you want them to be.&lt;/p&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;</description>
      <pubDate>Tue, 04 Apr 2006 21:16:11 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:4d1380d9-92c4-48e9-8c16-59a62b8a29c4</guid>
      <author>ben</author>
      <link>http://groovie.org/articles/2006/04/04/routes-1-3-1</link>
      <category>Python</category>
      <category>Routes</category>
    </item>
    <item>
      <title>Routes 1.2 Released</title>
      <description>&lt;p&gt;I got Routes 1.2 out the door today, it&amp;#8217;s a fairly important update for 2 reasons:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;A bug crept in with 1.1 using the default controller directory scanner. The scanner wasn&amp;#8217;t properly retaining the directory prefix which causes mismatches when using controllers underneath a sub-directory.&lt;/li&gt;
		&lt;li&gt;url_for can (and should) be used for all your &lt;span class="caps"&gt;URL&lt;/span&gt; needs, including static files&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;The second one is pretty important if you&amp;#8217;re at all interested in creating portable web applications that can be used along-side other applications. While some frameworks provide generation of &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s that lead to other web pages, hard-linking the other &amp;#8216;static&amp;#8217; content will cause problems if you try and use the application under a different mount point.&lt;/p&gt;


	&lt;p&gt;Instead of using a url like &lt;code&gt;/css/source.css&lt;/code&gt; it should instead be generated with &lt;code&gt;url_for('/css/source.css')&lt;/code&gt;. This way Routes can ensure that if you&amp;#8217;re running under a &lt;span class="caps"&gt;WSGI&lt;/span&gt; environment and there&amp;#8217;s a &lt;code&gt;SCRIPT_NAME&lt;/code&gt; present (this indicates the applications location), it will be pre-pended to your absolute &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s. When used like this, additional keyword arguments passed in will be used as query args on the &lt;span class="caps"&gt;URL&lt;/span&gt; making url_for a handy way to create &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s that are properly &lt;span class="caps"&gt;URL&lt;/span&gt; encoded.&lt;/p&gt;


	&lt;p&gt;Another useful feature that made it into 1.2 allows you to alias &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s you might want to use throughout your web application, I call these &lt;a href="http://routes.groovie.org/manual.html#static-named-routes"&gt;static named routes&lt;/a&gt;. An example can be found in the &lt;a href="http://routes.groovie.org/manual.html#named-routes"&gt;named routes section&lt;/a&gt; of the &lt;a href="http://routes.groovie.org/manual.html"&gt;Routes Manual&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Enjoy!&lt;/p&gt;</description>
      <pubDate>Fri, 17 Feb 2006 13:17:27 -0800</pubDate>
      <guid isPermaLink="false">urn:uuid:4a712bed-e922-4809-b381-f7607dfe4c92</guid>
      <author>ben</author>
      <link>http://groovie.org/articles/2006/02/17/routes-1-2-released</link>
      <category>Code</category>
      <category>Python</category>
      <category>Routes</category>
    </item>
    <item>
      <title>Routes 1.1 Released</title>
      <description>&lt;p&gt;I&amp;#8217;ve released &lt;a href="http://routes.groovie.org/"&gt;Routes 1.1&lt;/a&gt; today after extending the unit tests for the new Groupings syntax and updating the docs.&lt;/p&gt;


The new syntax is quite powerful and will hopefully make everyone using Routes rather happy. While I&amp;#8217;m not about to encourage anyone to use &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;#8217;s with .html at the end, there&amp;#8217;s plenty of times when you want extensions to mingle with dynamic parts. You can also get some useful abilities like being able to pull out the extension like so:
&lt;pre&gt;&lt;code&gt;
map.connect('archives/:category/:(section).:(format)', controller='archive', action='by_extension')
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This makes it easy to toggle the response depending on the extension, and the regexp business is handled for you.&lt;/p&gt;


	&lt;h4&gt;Integration Enhancements&lt;/h4&gt;


	&lt;p&gt;An additional feature, suggested by a Routes user was to make integration easier in &lt;span class="caps"&gt;WSGI&lt;/span&gt; environments. Earlier, at the beginning of each request you would have to populate the Routes config with the host, protocol, and match result. Now, merely passing the &lt;span class="caps"&gt;WSGI&lt;/span&gt; environ to the Routes config object will run a match, and populate those attributes for you.&lt;/p&gt;


	&lt;p&gt;The Routes Mapper now can take a function that when called returns a list of valid controllers. If you want to use the directory scanner Routes comes with, all you need to do is pass in the directory you&amp;#8217;d like to scan and Routes will scan it for you.&lt;/p&gt;


These two new integration improvements make it rather simple to integrate Routes, here&amp;#8217;s a basic &lt;span class="caps"&gt;WSGI&lt;/span&gt; app showing this off:
&lt;pre&gt;&lt;code&gt;
#myapp.py

from routes import *

map = Mapper(directory='/my/directory/of/controllers')
map.connect(':controller/:action/:id')
map.connect('home', '', controller='home', action='splash')

class WSGIApp(object):
    def __init__(self, mapper=map):
        self.mapper = mapper

    def __call__(self, environ, start_response):
        config = request_config()
        config.mapper = self.mapper
        config.environ = environ

        if not config.mapper_dict:
            start_response("404 Not Found", [("content-type","text/html")])
            return ["No match"]
        else:
            start_response("200 OK", [("content-type","text/html")])
            return ["Match with the following dict: %s" % str(config.mapper_dict)]
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;That&amp;#8217;s it! If you&amp;#8217;re not using &lt;span class="caps"&gt;WSGI&lt;/span&gt;, there&amp;#8217;s been no backwards breakage so the old style of setting up all the attributes of the config will work fine as well.&lt;/p&gt;


	&lt;p&gt;So, now I have to figure out if there&amp;#8217;s anything else Routes should possibly have&amp;#8230; or is the only space for improvement at this point further optimization and perhaps usability improvements?&lt;/p&gt;</description>
      <pubDate>Fri, 13 Jan 2006 14:21:01 -0800</pubDate>
      <guid isPermaLink="false">urn:uuid:dfc39d8d-8442-4d69-84fb-552e952a600b</guid>
      <author>ben</author>
      <link>http://groovie.org/articles/2006/01/13/routes-1-1-released</link>
      <category>Code</category>
      <category>Python</category>
      <category>Routes</category>
    </item>
    <item>
      <title>Routes 1.1 Preview</title>
      <description>&lt;p&gt;The major feature I was waiting on for Routes 1.1 is for the most part done, mainly adding more unit tests for the new syntax now. As I &lt;a href="http://groovie.org/articles/2005/11/21/routes-1-0-released"&gt;mentioned previously when announcing Routes 1.0&lt;/a&gt;, this feature is the one quite a few people have been waiting for. The ability to split the route path somewhere other than on a &lt;code&gt;/&lt;/code&gt;.&lt;/p&gt;


Here&amp;#8217;s what a few Routes using the new feature look like:
&lt;pre&gt;&lt;code&gt;
map.connect(':category/:(page).html', controller='stories', action='view')

map.connect('feeds/:(section).:(extension)', controller='feeds', action='formatter')

map.connect('archives/:(year):(month):(day).html', controller='archives', action='view',
          requirements=dict(year=r'\d{4}',month=r'\d{2}',day=r'\d{2}'))
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The new section dividers, &lt;code&gt;:(something)&lt;/code&gt; can be used side-by-side as the last example above shows, however in such cases each path part must have a rigid regexp requirement placed on it to ensure proper collection of the variables. Typically you will have some characters in between each dynamic part so this issue doesn&amp;#8217;t arise.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve retained full backward compatibility with the old syntax as well, if you don&amp;#8217;t designate the dynamic part using the &lt;code&gt;()&lt;/code&gt; modifier it will fall back to looking for the next &lt;code&gt;/&lt;/code&gt; instead. So far, all the existing (and &lt;strong&gt;extensive&lt;/strong&gt;) unit tests are passing, in addition to new tests I&amp;#8217;ve been adding.&lt;/p&gt;


Routes generates a full regular expression for &lt;span class="caps"&gt;URL&lt;/span&gt; matching based off the route path you give it. This makes it a great way to setup &lt;span class="caps"&gt;URL&lt;/span&gt; routing with the power of regexp&amp;#8217;s yet avoiding the hassle of writing a large complex regexp yourself. The other very powerful ability you gain is that Routes can turn the keywords back into the &lt;span class="caps"&gt;URL&lt;/span&gt;, like so:
&lt;pre&gt;&lt;code&gt;
&amp;gt;&amp;gt;&amp;gt; url_for(controller='archives', action='view', year=2004, month=10, day=12)
'/archives/20041012.html'

&amp;gt;&amp;gt;&amp;gt; url_for(controller='feeds',action='formatter',section='computers',extension='xml')
'/feeds/computers.xml'
&lt;/code&gt;&lt;/pre&gt;

If you&amp;#8217;re interested in giving it a spin, it can be checked out and installed easily from the svn repository using setuptools:
&lt;pre&gt;
sudo easy_install -U http://routes.groovie.org/svn/branches/newsplit
&lt;/pre&gt;

	&lt;p&gt;Feedback / Suggestions / Bug Reports greatly appreciated.&lt;/p&gt;</description>
      <pubDate>Tue, 03 Jan 2006 09:35:43 -0800</pubDate>
      <guid isPermaLink="false">urn:uuid:e1c840ba-0f4e-4967-baa5-03c9f009ffc3</guid>
      <author>ben</author>
      <link>http://groovie.org/articles/2006/01/03/routes-1-1-preview</link>
      <category>Code</category>
      <category>Python</category>
      <category>Routes</category>
    </item>
  </channel>
</rss>
