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

Ticket #800: error_page_callable.patch

  • _cperror.py

    old new  
    148148        raise self 
    149149 
    150150 
     151def clean_headers(status): 
     152    """Remove any headers which should not apply to an error response.""" 
     153    import cherrypy 
     154     
     155    response = cherrypy.response 
     156     
     157    # Remove headers which applied to the original content, 
     158    # but do not apply to the error page. 
     159    respheaders = response.headers 
     160    for key in ["Accept-Ranges", "Age", "ETag", "Location", "Retry-After", 
     161                "Vary", "Content-Encoding", "Content-Length", "Expires", 
     162                "Content-Location", "Content-MD5", "Last-Modified"]: 
     163        if respheaders.has_key(key): 
     164            del respheaders[key] 
     165     
     166    if status != 416: 
     167        # A server sending a response with status code 416 (Requested 
     168        # range not satisfiable) SHOULD include a Content-Range field 
     169        # with a byte-range-resp-spec of "*". The instance-length 
     170        # specifies the current length of the selected resource. 
     171        # A response with status code 206 (Partial Content) MUST NOT 
     172        # include a Content-Range field with a byte-range- resp-spec of "*". 
     173        if respheaders.has_key("Content-Range"): 
     174            del respheaders["Content-Range"] 
     175 
     176 
    151177class HTTPError(CherryPyException): 
    152178    """ Exception used to return an HTTP error code (4xx-5xx) to the client. 
    153179        This exception will automatically set the response status and body. 
     
    173199         
    174200        response = cherrypy.response 
    175201         
    176         # Remove headers which applied to the original content, 
    177         # but do not apply to the error page. 
    178         respheaders = response.headers 
    179         for key in ["Accept-Ranges", "Age", "ETag", "Location", "Retry-After", 
    180                     "Vary", "Content-Encoding", "Content-Length", "Expires", 
    181                     "Content-Location", "Content-MD5", "Last-Modified"]: 
    182             if respheaders.has_key(key): 
    183                 del respheaders[key] 
     202        clean_headers(self.status) 
    184203         
    185         if self.status != 416: 
    186             # A server sending a response with status code 416 (Requested 
    187             # range not satisfiable) SHOULD include a Content-Range field 
    188             # with a byte-range-resp-spec of "*". The instance-length 
    189             # specifies the current length of the selected resource. 
    190             # A response with status code 206 (Partial Content) MUST NOT 
    191             # include a Content-Range field with a byte-range- resp-spec of "*". 
    192             if respheaders.has_key("Content-Range"): 
    193                 del respheaders["Content-Range"] 
    194          
    195204        # In all cases, finalize will be called after this method, 
    196205        # so don't bother cleaning up response values here. 
    197206        response.status = self.status 
    198207        tb = None 
    199208        if cherrypy.request.show_tracebacks: 
    200209            tb = format_exc() 
    201         respheaders['Content-Type'] = "text/html" 
     210        response.headers['Content-Type'] = "text/html" 
    202211         
    203212        content = self.get_error_page(self.status, traceback=tb, 
    204213                                      message=self.message) 
    205214        response.body = content 
    206         respheaders['Content-Length'] = len(content) 
     215        response.headers['Content-Length'] = len(content) 
    207216         
    208217        _be_ie_unfriendly(self.status) 
    209218     
  • _cprequest.py

    old new  
    591591                    self.hooks.run('before_finalize') 
    592592                    cherrypy.response.finalize() 
    593593                except (cherrypy.HTTPRedirect, cherrypy.HTTPError), inst: 
    594                     inst.set_response() 
     594                    ep = self.error_page.get(inst.status, '') 
     595                    if ep and callable(ep): 
     596                        ep(inst) 
     597                    else: 
     598                        inst.set_response() 
    595599                    self.stage = 'before_finalize (HTTPError)' 
    596600                    self.hooks.run('before_finalize') 
    597601                    cherrypy.response.finalize() 
     
    715719            self.params.update(p) 
    716720     
    717721    def handle_error(self, exc): 
    718         """Handle the last exception. (Core)""" 
     722        """Handle the last unanticipated exception. (Core)""" 
    719723        try: 
    720724            self.hooks.run("before_error_response") 
    721725            if self.error_response: 
     
    723727            self.hooks.run("after_error_response") 
    724728            cherrypy.response.finalize() 
    725729        except cherrypy.HTTPRedirect, inst: 
    726             inst.set_response() 
     730            ep = self.error_page.get(inst.status, '') 
     731            if ep and callable(ep): 
     732                ep(inst) 
     733            else: 
     734                inst.set_response() 
    727735            cherrypy.response.finalize() 
    728736 
    729737 
  • test/test_core.py

    old new  
    239239        def as_refyield(self): 
    240240            for chunk in self.as_yield(): 
    241241                yield chunk 
    242  
    243  
     242     
     243     
     244    def page401(e): 
     245        cherrypy.response.status = e.status 
     246        cherrypy._cperror.clean_headers(e.status) 
     247        cherrypy.response.body = "Well, I'm very sorry but you haven't paid!" 
     248     
     249     
    244250    class Error(Test): 
    245251         
    246252        _cp_config = {'tools.log_tracebacks.on': True, 
    247253                      } 
    248254         
    249         def custom(self): 
    250             raise cherrypy.HTTPError(404, "No, <b>really</b>, not found!") 
    251         custom._cp_config = {'error_page.404': os.path.join(localDir, "static/index.html")} 
     255        def custom(self, err='404'): 
     256            raise cherrypy.HTTPError(int(err), "No, <b>really</b>, not found!") 
     257        custom._cp_config = {'error_page.404': os.path.join(localDir, "static/index.html"), 
     258                             'error_page.401': page401, 
     259                             } 
    252260         
    253261        def noexist(self): 
    254262            raise cherrypy.HTTPError(404, "No, <b>really</b>, not found!") 
     
    725733        self.assertStatus(404) 
    726734        self.assertBody("Hello, world\r\n" + (" " * 499)) 
    727735         
     736        # Test custom error page. 
     737        self.getPage("/error/custom?err=401") 
     738        self.assertStatus(401) 
     739        self.assertBody("Well, I'm very sorry but you haven't paid!") 
     740         
    728741        # Test error in custom error page (ticket #305). 
    729742        # Note that the message is escaped for HTML (ticket #310). 
    730743        self.getPage("/error/noexist") 

Hosted by WebFaction

Log in as guest/cpguest to create tickets