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

Changeset 1730

Show
Ignore:
Timestamp:
09/27/07 15:39:42
Author:
fumanchu
Message:

More from [1711]. I'm porting this in two commits to make the diffs easier to read, so trunk is broken right now.

Files:

Legend:

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

    r1677 r1730  
    5555            nextapp = self.default 
    5656        return nextapp(environ, start_response) 
    57  
    58  
    59 #                            Internal Redirect                            # 
    60  
    61  
    62 class InternalRedirector(object): 
    63     """WSGI middleware which handles cherrypy.InternalRedirect. 
    64      
    65     When cherrypy.InternalRedirect is raised, this middleware traps it, 
    66     rewrites the WSGI environ using the new path and query_string, 
    67     and calls the next application again. Because the wsgi.input stream 
    68     may have already been consumed by the next application, the redirected 
    69     call will always be of HTTP method "GET", and therefore any params must 
    70     be passed in the InternalRedirect object's query_string attribute. 
    71     If you need something more complicated, make and raise your own 
    72     exception and your own WSGI middleware to trap it. ;) 
    73      
    74     It would be a bad idea to raise InternalRedirect after you've already 
    75     yielded response content, although an enterprising soul could choose 
    76     to abuse this. 
    77      
    78     nextapp: the next application callable in the WSGI chain. 
    79      
    80     recursive: if False (the default), each URL (path + qs) will be 
    81     stored, and, if the same URL is requested again, RuntimeError will 
    82     be raised. If 'recursive' is True, no such error will be raised. 
    83     """ 
    84      
    85     def __init__(self, nextapp, recursive=False): 
    86         self.nextapp = nextapp 
    87         self.recursive = recursive 
    88      
    89     def __call__(self, environ, start_response): 
    90         return IRResponse(self.nextapp, environ, start_response, self.recursive) 
    91  
    92  
    93 class IRResponse(object): 
    94      
    95     def __init__(self, nextapp, environ, start_response, recursive): 
    96         self.redirections = [] 
    97         self.recursive = recursive 
    98         self.environ = environ.copy() 
    99         self.nextapp = nextapp 
    100         self.start_response = start_response 
    101         self.response = None 
    102         self.iter_response = None 
    103         self.setapp() 
    104      
    105     def setapp(self): 
    106         while True: 
    107             try: 
    108                 self.response = self.nextapp(self.environ, self.start_response) 
    109                 self.iter_response = iter(self.response) 
    110                 return 
    111             except _cherrypy.InternalRedirect, ir: 
    112                 self.close() 
    113                 self.setenv(ir) 
    114      
    115     def setenv(self, ir): 
    116         env = self.environ 
    117         if not self.recursive: 
    118             if ir.path in self.redirections: 
    119                 raise RuntimeError("InternalRedirector visited the " 
    120                                    "same URL twice: %r" % ir.path) 
    121             else: 
    122                 # Add the *previous* path_info + qs to redirections. 
    123                 sn = env.get('SCRIPT_NAME', '') 
    124                 path = env.get('PATH_INFO', '') 
    125                 qs = env.get('QUERY_STRING', '') 
    126                 if qs: 
    127                     qs = "?" + qs 
    128                 self.redirections.append(_http.urljoin(sn, path) + qs) 
    129          
    130         # Munge environment and try again. 
    131         env['REQUEST_METHOD'] = "GET" 
    132         env['PATH_INFO'] = ir.path 
    133         env['QUERY_STRING'] = ir.query_string 
    134         env['wsgi.input'] = _StringIO.StringIO() 
    135         env['CONTENT_LENGTH'] = "0" 
    136      
    137     def close(self): 
    138         if hasattr(self.response, "close"): 
    139             self.response.close() 
    140      
    141     def __iter__(self): 
    142         return self 
    143      
    144     def next(self): 
    145         while True: 
    146             try: 
    147                 return self.iter_response.next() 
    148             except _cherrypy.InternalRedirect, ir: 
    149                 self.close() 
    150                 self.setenv(ir) 
    151                 self.setapp() 
    15257 
    15358 

Hosted by WebFaction

Log in as guest/cpguest to create tickets