Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 1310

Show
Ignore:
Timestamp:
09/02/06 02:11:01
Author:
fumanchu
Message:

Fix for #559 (allow config of WSGI middleware) via cherrypy.wsgi.pipeline. Includes tests.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/_cpwsgi.py

    r1309 r1310  
    44from cherrypy import _cpwsgiserver 
    55from cherrypy.lib import http as _http 
     6 
     7 
     8class pipeline(list): 
     9    """An ordered list of configurable WSGI middleware. 
     10     
     11    self: a list of (name, wsgiapp) pairs. Each 'wsgiapp' MUST be a 
     12        constructor that takes an initial, positional wsgiapp argument, 
     13        plus optional keyword arguments, and returns a WSGI application 
     14        (that takes environ and start_response arguments). The 'name' can 
     15        be any you choose, and will correspond to keys in self.config. 
     16    config: a dict whose keys match names listed in the pipeline. Each 
     17        value is a further dict which will be passed to the corresponding 
     18        named WSGI callable (from the pipeline) as keyword arguments. 
     19    """ 
     20     
     21    def __new__(cls, app, members=None, key="wsgi"): 
     22        return list.__new__(cls) 
     23     
     24    def __init__(self, app, members=None, key="wsgi"): 
     25        self.app = app 
     26        if members: 
     27            self.extend(members) 
     28        self.head = None 
     29        self.tail = None 
     30        self.config = {} 
     31        self.key = key 
     32        app.namespaces[key] = self.namespace_handler 
     33        app.wsgi_pipeline = self 
     34     
     35    def namespace_handler(self, k, v): 
     36        """Config handler for our namespace.""" 
     37        if k == "pipeline": 
     38            # Note this allows multiple entries to be aggregated (but also 
     39            # note dicts are essentially unordered). It should also allow 
     40            # developers to set default middleware in code (passed to 
     41            # pipeline.__init__) that deployers can add to but not remove. 
     42            self.extend(v) 
     43             
     44            if self: 
     45                # If self is empty, there's no need to replace app.wsgiapp. 
     46                # Also note we're grabbing app.wsgiapp, not app.__call__, 
     47                # so we can "play nice" with other Application-manglers 
     48                # (hopefully, they'll do the same). 
     49                self.tail = self.app.wsgiapp 
     50                self.app.wsgiapp = self.__call__ 
     51        else: 
     52            name, arg = k.split(".", 1) 
     53            bucket = self.config.setdefault(name, {}) 
     54            bucket[arg] = v 
     55     
     56    def __call__(self, environ, start_response): 
     57        if not self.head: 
     58            # This class may be used without calling namespace_handler, 
     59            # in which case self.tail may still be None. 
     60            self.head = self.tail or self.app.wsgiapp 
     61            pipe = self[:] 
     62            pipe.reverse() 
     63            for name, callable in pipe: 
     64                conf = self.config.get(name, {}) 
     65                self.head = callable(self.head, **conf) 
     66        return self.head(environ, start_response) 
     67     
     68    def __repr__(self): 
     69        return "%s.%s(%r)" % (self.__module__, self.__class__.__name__, 
     70                              list(self)) 
    671 
    772 
  • trunk/cherrypy/test/test.py

    r1278 r1310  
    323323        'test_xmlrpc', 
    324324        'test_wsgiapps', 
     325        'test_wsgi_ns', 
    325326    ] 
    326327    CommandLineParser(testList).run() 

Hosted by WebFaction

Log in as guest/cpguest to create tickets