[Web-SIG] Proposal: wsgi.url_vars
Ian Bicking
ianb at colorstudy.com
Sat Oct 21 19:49:06 CEST 2006
I think there's room for some more standards building on WSGI (that
aren't actually extensions of the WSGI spec itself).
I put a page up on the wsgi.org site for this:
http://wsgi.org/wsgi/Specifications
And I'm introducing what I think is low-hanging fruit in the
specification realm: wsgi.url_vars
http://wsgi.org/wsgi/Specifications/url_vars
The spec is copied below for discussion:
:Title: wsgi.url_vars
:Author: Ian Bicking <ianb at colorstudy.com>
:Discussions-To: Python Web-SIG <web-sig at python.org>
:Status: Draft
:Created: 21-Oct-2006
.. contents::
Abstract
--------
This proposes a new standard environment key
``environ['wsgi.url_vars']`` to represent the results of more
complicated URL parsing strategies.
Rationale
---------
WSGI currently specifies the meaning of ``SCRIPT_NAME`` and
``PATH_INFO``, which allows generic prefix-based dispatchers to be
created. These dispatchers can work with any WSGI application that
respects the meaning of these two variables. The basic meaning of
``SCRIPT_NAME`` is *the portion of the path that has been consumed* and
``PATH_INFO`` is *the portion of the path left to the application*.
Using these two variables more complex dispatchers cannot represent the
information they pull out of the request path. This specification
simply defines a place where such dispatchers can put their information:
``wsgi.url_vars``.
Specification
-------------
This specification defines a new key that can go in the WSGI
environment, ``wsgi.url_vars``. This key is optional.
If a dispatcher (like `routes <http://routes.groovie.org/>`_ or
`selector <http://lukearno.com/projects/selector/>`_) pulls named
information out of the portion of the request path it parses, it can put
that information into a dictionary in ``environ['wsgi.url_vars']``.
Portions of the path that have been parsed should still be moved to
``SCRIPT_NAME`` (and removed from ``PATH_INFO``).
Example
-------
This example is a dispatcher that is given regular expressions and
matching applications. It checks each regular expression in turn, and
when one matches it moves the named groups into ``wsgi.url_vars`` and
dispatches to the associated application.
::
class RegexDispatch(object):
def __init__(self, patterns):
self.patterns = patters
def __call__(self, environ, start_response):
script_name = environ.get('SCRIPT_NAME', '')
path_info = environ.get('PATH_INFO', '')
for regex, application in self.patterns:
match = regex.match(path_info)
if not match:
continue
extra_path_info = path_info[match.end():]
if extra_path_info and not extra_path_info.startswith('/'):
# Not a very good match
continue
groups = match.groupdict()
environ.setdefault('wsgi.url_vars', {}).update(groups)
environ['SCRIPT_NAME'] = script_name +
path_info[:match.end()]
environ['PATH_INFO'] = extra_path_info
return application(environ, start_response)
return self.not_found(environ, start_response)
def not_found(self, environ, start_response):
start_response('404 Not Found', [('Content-type',
'text/plain')])
return ['Not found']
dispatch_app = RegexDispatch([
(re.compile(r'/archive/(?P<year>\d{4})/$'), archive_app),
(re.compile(r'/archive/(?P<year>\d{4})/(?P<month>\d{2})/$'),
archive_app),
(re.compile(r'/archive/(?P<year>\d{4})/(?P<month>\d{2})/(?P<article_id>\d+)$'),
view_article),
])
More information about the Web-SIG
mailing list