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

Changeset 1321

Show
Ignore:
Timestamp:
09/02/06 14:42:12
Author:
fumanchu
Message:

Fix for #556 (Allow error hooks to raise InternalRedirect?). As a bonus, all uncaught errors in Request.run now get a fallback handler (before only errors in handle_error got that).

Files:

Legend:

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

    r1311 r1321  
    321321    body = None 
    322322    body_read = False 
     323    headers_read = False 
    323324     
    324325    # Dispatch attributes 
     
    439440            self.handler = None 
    440441             
    441             # Get the 'Host' header, so we can do HTTPRedirects properly. 
    442             self.process_headers() 
    443              
    444442            # path_info should be the path from the 
    445443            # app root (script_name) to the handler. 
     
    461459        except (KeyboardInterrupt, SystemExit): 
    462460            raise 
    463         except cherrypy.TimeoutError: 
     461        except: 
     462            if self.throw_errors: 
     463                raise 
     464            else: 
     465                # Can't use handle_error because we may not have hooks yet. 
     466                cherrypy.log(traceback=True) 
     467                 
     468                # Failure in setup, error handler or finalize. Bypass them. 
     469                if self.show_tracebacks: 
     470                    exc = sys.exc_info() 
     471                    try: 
     472                        dbltrace = ("\n===First Error===\n\n%s" 
     473                                    "\n\n===Second Error===\n\n%s\n\n") 
     474                        body = dbltrace % (format_exc(exc), format_exc()) 
     475                    finally: 
     476                        del exc 
     477                else: 
     478                    body = "" 
     479                r = bare_error(body) 
     480                response = cherrypy.response 
     481                response.status, response.header_list, response.body = r 
     482         
     483        if self.method == "HEAD": 
     484            # HEAD requests MUST NOT return a message-body in the response. 
     485            cherrypy.response.body = [] 
     486         
     487        cherrypy.log.access() 
     488         
     489        return cherrypy.response 
     490     
     491    def respond(self, path_info): 
     492        """Generate a response for the resource at self.path_info.""" 
     493        try: 
     494            try: 
     495                try: 
     496                    if cherrypy.response.timed_out: 
     497                        raise cherrypy.TimeoutError() 
     498                     
     499                    if self.app is None: 
     500                        raise cherrypy.NotFound() 
     501                     
     502                    if not self.headers_read: 
     503                        # Get the 'Host' header, so we can do HTTPRedirects properly. 
     504                        self.process_headers() 
     505                     
     506                    self.hooks = HookMap(self.hookpoints) 
     507                    self.get_resource(path_info) 
     508                    self.tool_up() 
     509                     
     510                    self.hooks.run('on_start_resource') 
     511                     
     512                    if not self.body_read: 
     513                        if self.process_request_body: 
     514                            if self.method not in self.methods_with_bodies: 
     515                                self.process_request_body = False 
     516                         
     517                        if self.process_request_body: 
     518                            # Prepare the SizeCheckWrapper for the request body 
     519                            mbs = cherrypy.server.max_request_body_size 
     520                            if mbs > 0: 
     521                                self.rfile = http.SizeCheckWrapper(self.rfile, mbs) 
     522                     
     523                    self.hooks.run('before_request_body') 
     524                    if self.process_request_body: 
     525                        self.process_body() 
     526                     
     527                    self.hooks.run('before_main') 
     528                    if self.handler: 
     529                        self.handler() 
     530                    self.hooks.run('before_finalize') 
     531                    cherrypy.response.finalize() 
     532                except (cherrypy.HTTPRedirect, cherrypy.HTTPError), inst: 
     533                    inst.set_response() 
     534                    self.hooks.run('before_finalize') 
     535                    cherrypy.response.finalize() 
     536            finally: 
     537                self.hooks.run('on_end_resource') 
     538        except cherrypy.InternalRedirect: 
    464539            raise 
    465540        except: 
     
    467542                raise 
    468543            self.handle_error(sys.exc_info()) 
    469          
    470         if self.method == "HEAD": 
    471             # HEAD requests MUST NOT return a message-body in the response. 
    472             cherrypy.response.body = [] 
    473          
    474         cherrypy.log.access() 
    475          
    476         return cherrypy.response 
    477      
    478     def respond(self, path_info): 
    479         """Generate a response for the resource at self.path_info.""" 
    480         try: 
    481             try: 
    482                 if cherrypy.response.timed_out: 
    483                     raise cherrypy.TimeoutError() 
    484                  
    485                 if self.app is None: 
    486                     raise cherrypy.NotFound() 
    487                  
    488                 self.hooks = HookMap(self.hookpoints) 
    489                 self.get_resource(path_info) 
    490                 self.tool_up() 
    491                 self.hooks.run('on_start_resource') 
    492                  
    493                 if not self.body_read: 
    494                     if self.process_request_body: 
    495                         if self.method not in self.methods_with_bodies: 
    496                             self.process_request_body = False 
    497                      
    498                     if self.process_request_body: 
    499                         # Prepare the SizeCheckWrapper for the request body 
    500                         mbs = cherrypy.server.max_request_body_size 
    501                         if mbs > 0: 
    502                             self.rfile = http.SizeCheckWrapper(self.rfile, mbs) 
    503                  
    504                 self.hooks.run('before_request_body') 
    505                 if self.process_request_body: 
    506                     self.process_body() 
    507                  
    508                 self.hooks.run('before_main') 
    509                 if self.handler: 
    510                     self.handler() 
    511                 self.hooks.run('before_finalize') 
    512                 cherrypy.response.finalize() 
    513             except (cherrypy.HTTPRedirect, cherrypy.HTTPError), inst: 
    514                 inst.set_response() 
    515                 self.hooks.run('before_finalize') 
    516                 cherrypy.response.finalize() 
    517         finally: 
    518             self.hooks.run('on_end_resource') 
    519544     
    520545    def process_headers(self): 
     546        # Guard against re-reading body (e.g. on InternalRedirect) 
     547        if self.headers_read: 
     548            return 
     549        self.headers_read = True 
     550         
    521551        self.params = http.parse_query_string(self.query_string) 
    522552         
     
    648678     
    649679    def handle_error(self, exc): 
    650         response = cherrypy.response 
    651680        try: 
    652681            self.hooks.run("before_error_response") 
     
    654683                self.error_response() 
    655684            self.hooks.run("after_error_response") 
    656             response.finalize() 
    657             return 
     685            cherrypy.response.finalize() 
    658686        except cherrypy.HTTPRedirect, inst: 
    659             try: 
    660                 inst.set_response() 
    661                 response.finalize() 
    662                 return 
    663             except (KeyboardInterrupt, SystemExit): 
    664                 raise 
    665             except: 
    666                 # Fall through to the second error handler 
    667                 pass 
    668         except (KeyboardInterrupt, SystemExit): 
    669             raise 
    670         except: 
    671             # Fall through to the second error handler 
    672             pass 
    673          
    674         # Failure in error handler or finalize. Bypass them. 
    675         if self.show_tracebacks: 
    676             dbltrace = ("\n===First Error===\n\n%s" 
    677                         "\n\n===Second Error===\n\n%s\n\n") 
    678             body = dbltrace % (format_exc(exc), format_exc()) 
    679         else: 
    680             body = "" 
    681         r = bare_error(body) 
    682         response.status, response.header_list, response.body = r 
     687            inst.set_response() 
     688            cherrypy.response.finalize() 
    683689 
    684690 
  • trunk/cherrypy/test/test_core.py

    r1318 r1321  
    135135            return str(cherrypy.HTTPRedirect("/")) 
    136136     
     137     
    137138    def login_redir(): 
    138139        if not getattr(cherrypy.request, "login", None): 
    139140            raise cherrypy.InternalRedirect("/internalredirect/login") 
    140141    tools.login_redir = _cptools.Tool('before_main', login_redir) 
     142     
     143    def redir_custom(): 
     144        raise cherrypy.InternalRedirect("/internalredirect/custom_err") 
    141145     
    142146    class InternalRedirect(Test): 
     
    173177        def login(self): 
    174178            return "Please log in" 
    175  
    176  
     179        login._cp_config = {'hooks.before_error_response': redir_custom} 
     180         
     181        def custom_err(self): 
     182            return "Something went horribly wrong." 
     183     
    177184    class Image(Test): 
    178185         
     
    572579        self.assertBody('I am a redirected page.') 
    573580        self.assertStatus(200) 
     581         
     582        # InternalRedirect on error 
     583        self.getPage("/internalredirect/login/illegal/extra/vpath/atoms") 
     584        self.assertStatus(200) 
     585        self.assertBody("Something went horribly wrong.") 
    574586         
    575587        # HTTPRedirect on error 

Hosted by WebFaction

Log in as guest/cpguest to create tickets