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

Changeset 640

Show
Ignore:
Timestamp:
09/13/05 18:56:39
Author:
fumanchu
Message:

Merges from trunk [639].

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/filterorder/cherrypy/_cpcgifs.py

    r622 r640  
    99        except ValueError, ex: 
    1010            if str(ex) == 'Maximum content length exceeded': 
    11                 raise cherrypy.HTTPStatusError(status=413) 
     11                raise cherrypy.HTTPError(status=413) 
    1212            else: 
    1313                raise ex 
  • branches/filterorder/cherrypy/_cperror.py

    r613 r640  
    173173_missing = object() 
    174174 
    175 class HTTPStatusError(Error): 
    176     """Exception raised when the client has made an error in its request.""" 
    177      
    178     def __init__(self, status=400, message=_missing): 
     175class HTTPError(Error): 
     176    """ Exception raised when the client has made an error in its request. 
     177        This exception will automatically set the response status and body. 
     178         
     179        A custom body can be pased to the init method in place of the standard error page. 
     180    """ 
     181     
     182    def __init__(self, status=500, body=_missing): 
    179183        self.status = status = int(status) 
    180184        if status < 400 or status > 599: 
     
    183187        # these 4 lines might dissapear 
    184188        import cherrypy 
    185         cherrypy.response.status = status 
    186         if message is not _missing: 
    187             cherrypy.response.body=message 
    188  
    189         self.message = message 
    190      
    191     def getArgs(self): 
    192         return (self.status, self.message) 
    193  
    194  
    195 class NotFound(HTTPStatusError): 
     189        self.statusString = cherrypy._cputil.getErrorStatusAndPage(status)[0] 
     190        cherrypy.response.status = self.statusString 
     191 
     192        if body is _missing: 
     193            # because the init method is called before the exception is raised 
     194            # it is impossible to embed the traceback in the error page at this point. 
     195            # We use a generator so that the error page is generated at a later point ( 
     196            # after the exception is raised). 
     197            cherrypy.response.body = self.pageGenerator() 
     198        else: 
     199            cherrypy.response.body = body 
     200     
     201    def __str__(self): 
     202        return self.statusString 
     203 
     204    def pageGenerator(self): 
     205        import cherrypy 
     206        yield cherrypy._cputil.getErrorStatusAndPage(self.status)[1] 
     207 
     208class NotFound(HTTPError): 
    196209    """ Happens when a URL couldn't be mapped to any class.method """ 
    197210     
    198211    def __init__(self, path): 
    199212        self.args = (path,) 
    200         HTTPStatusError.__init__(self, 404) 
     213        HTTPError.__init__(self, 404) 
  • branches/filterorder/cherrypy/_cphttptools.py

    r638 r640  
    291291                applyFilters('onEndResource') 
    292292        except: 
    293             # This includes HTTPStatusError and NotFound 
     293            # This includes HTTPError and NotFound 
    294294            handleError(sys.exc_info()) 
    295295     
     
    383383        except _cpwsgiserver.MaxSizeExceeded: 
    384384            # Post data is too big 
    385             raise _cperror.HTTPStatusError(413) 
     385            raise _cperror.HTTPError(413) 
    386386         
    387387        if forms.file: 
     
    425425        applyFilters('beforeErrorResponse') 
    426426         
    427         # _cpOnError and _cpOnHTTPError will probably change cherrypy.response.body. 
     427        # _cpOnError will probably change cherrypy.response.body. 
    428428        # They may also change the headerMap, etc. 
    429         if sys.exc_info()[0] is cherrypy.HTTPStatusError: 
    430             getSpecialAttribute('_cpOnHTTPError')() 
    431         else: 
    432             getSpecialAttribute('_cpOnError')() 
     429        _cputil.getSpecialAttribute('_cpOnError')() 
    433430         
    434431        finalize() 
  • branches/filterorder/cherrypy/_cputil.py

    r638 r640  
    3636 
    3737import cherrypy 
    38 from cherrypy.lib import httperrors 
    39  
    4038 
    4139class EmptyClass: 
     
    154152        f.close() 
    155153 
    156 def _cpOnHTTPError(): 
    157     """ Default _cpOnHTTPError method """ 
    158     status, customMessage = sys.exc_info()[1].getArgs() 
    159     
    160     # get the error page 
    161     page = httperrors.getErrorPage(status, customMessage = customMessage) 
    162     cherrypy.response.status, cherrypy.response.body = page 
    163      
    164     if cherrypy.response.headerMap.has_key('Content-Encoding'): 
    165         del cherrypy.response.headerMap['Content-Encoding'] 
     154def _HTTPErrorTemplate(errorString, message, traceback, version): 
     155    subTuple = (errorString, errorString, message, traceback, cherrypy.__version__) 
     156     
     157    return '''<?xml version="1.0" encoding="UTF-8"?> 
     158    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
     159      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
     160    <html> 
     161    <head> 
     162        <title>%s</title> 
     163        <style type="text/css"> 
     164        #poweredBy { 
     165            margin-top: 20px; 
     166            border-top: 2px solid black; 
     167            font-style: italic; 
     168        } 
     169 
     170        #traceback { 
     171            color: red; 
     172        } 
     173        </style> 
     174    </head> 
     175        <body> 
     176            <h2>%s</h2> 
     177            <p>%s</p> 
     178            <pre id="traceback">%s</pre> 
     179        <div id="poweredBy"> 
     180        <span>Powered by <a href="http://www.cherrypy.org">Cherrypy %s</a></span> 
     181        </div> 
     182        </body> 
     183    </html> 
     184    ''' % subTuple 
     185 
     186import BaseHTTPServer 
     187_HTTPResponses = BaseHTTPServer.BaseHTTPRequestHandler.responses 
     188 
     189def getErrorStatusAndPage(status, traceback = None): 
     190    statusString, message = _HTTPResponses[status] 
     191    statusString = '%d %s' % (status, statusString) 
     192     
     193    if traceback is None: 
     194        traceback = '' 
     195        # get the traceback from formatExc 
     196        developmentMode = (cherrypy.config.get('server.environment') == 'development') 
     197        if cherrypy.config.get('server.showTracebacks') or developmentMode: 
     198            traceback = formatExc() 
     199     
     200    page = _HTTPErrorTemplate(statusString, message, traceback, cherrypy.__version__) 
     201     
     202    return statusString, page 
    166203 
    167204def formatExc(exc=None): 
     
    169206    if exc is None: 
    170207        exc = sys.exc_info() 
     208 
     209    if exc == (None, None, None): 
     210        return "" 
     211    return "".join(traceback.format_exception(*exc)) 
     212 
     213def getErrorStatusAndPage(status, traceback = None): 
     214    statusString, message = _HTTPResponses[status] 
     215    statusString = '%d %s' % (status, statusString) 
     216     
     217    if traceback is None: 
     218        traceback = '' 
     219        # get the traceback from formatExc 
     220        developmentMode = (cherrypy.config.get('server.environment') == 'development') 
     221        if cherrypy.config.get('server.showTracebacks') or developmentMode: 
     222            traceback = formatExc() 
     223     
     224    page = _HTTPErrorTemplate(statusString, message, traceback, cherrypy.__version__) 
     225     
     226    return statusString, page 
     227 
     228    """formatExc(exc=None) -> exc (or sys.exc_info), formatted.""" 
     229    if exc is None: 
     230        exc = sys.exc_info() 
     231     
     232    if exc == (None, None, None): 
     233        return "" 
     234 
    171235    return "".join(traceback.format_exception(*exc)) 
    172236 
    173237def _cpOnError(): 
    174238    """ Default _cpOnError method """ 
    175     developmentMode = cherrypy.config.get('server.environment') == 'development' 
    176     httpErrors      = cherrypy.config.get('server.httpErrors') 
    177     showTracebacks  = cherrypy.config.get('server.showTracebacks') 
    178239     
    179240    logTracebacks  = cherrypy.config.get('server.logTracebacks', True) 
     
    183244    response = cherrypy.response 
    184245     
    185     if not developmentMode and httpErrors: 
    186         # if it isn't development mode and http errors are turned on 
    187         # set the response status and render the body 
    188         if response.status == 404: 
    189             response.status, response.body = httperrors.getErrorPage(404) 
    190         else: 
    191             response.status, response.body = httperrors.getErrorPage(500) 
    192     elif developmentMode or showTracebacks: 
    193         # if it is development mode or tracebacks are turned on 
    194         # return the traceback as plaintext 
    195         response.body = [formatExc()] 
    196         response.headerMap['Content-Type'] = 'text/plain' 
     246    if isinstance(sys.exc_info()[1], cherrypy.HTTPError): 
     247        # status, body already set 
     248        pass 
    197249    else: 
    198         # If it is production mode but http errors are disabled then 
    199         # Display a simple, generic error message 
    200         response.body = "Unrecoverable error in the server" 
    201         response.headerMap['Content-Type'] = 'text/plain' 
     250        response.status, response.body = getErrorStatusAndPage(500) 
    202251     
    203252    if cherrypy.response.headerMap.has_key('Content-Encoding'): 
  • branches/filterorder/cherrypy/lib/cptools.py

    r608 r640  
    206206        cherrypy.response.headerMap['Content-Range'] = "bytes */%s" % content_length 
    207207        message = "Invalid Range (first-byte-pos greater than Content-Length)" 
    208         raise cherrypy.HTTPStatusError(416, message) 
     208        raise cherrypy.HTTPError(416, message) 
    209209     
    210210    return result 
  • branches/filterorder/cherrypy/test/helper.py

    r638 r640  
    3939import webtest 
    4040import types 
     41import re 
     42 
    4143for _x in dir(cherrypy): 
    4244    y = getattr(cherrypy, _x) 
     
    129131        else: 
    130132            webtest.WebCase.getPage(self, url, headers, method, body) 
     133  
     134    def assertErrorPage(self, errorCode, pattern = ''): 
     135        """ Compare the response body with a built in error page. 
     136            The function will optionally look for the regexp pattern,  
     137            within the exception embedded in the error page. 
     138        """ 
     139 
     140        from cherrypy._cputil import getErrorStatusAndPage 
     141        page = getErrorStatusAndPage(errorCode, '')[1] 
     142 
     143        # escape the question marks 
     144        page = page.replace('?', r'\?') 
     145         
     146        # re to find the traceback in the page 
     147        traceRe = re.compile('(<pre id="traceback">)(</pre>)') 
     148 
     149        # stick the pattern in the page so we can match everythign 
     150        # at once 
     151        page = traceRe.sub( '\g<1>.*%s.*\g<2>' % pattern, page) 
     152         
     153        # check if there is no exception 
     154        if pattern and traceRe.search(self.body): 
     155            msg = 'No match for %s in body' % `pattern` 
     156            self._handlewebError(msg) 
     157        else: 
     158            if not re.search(page, self.body, re.DOTALL): 
     159                msg = 'Error page does not match' 
     160                self._handlewebError(msg) 
    131161 
    132162CPTestLoader = webtest.ReloadingTestLoader() 
  • branches/filterorder/cherrypy/test/test_core.py

    r638 r640  
    490490        self.getPage("/error/missing") 
    491491        self.assertStatus("404 Not Found") 
    492         self.assertInBody("NotFound"
     492        self.assertErrorPage(404
    493493         
    494494        ignore = helper.webtest.ignored_exceptions 
    495495        ignore.append(ValueError) 
    496496        try: 
    497             valerr = r'\n    raise ValueError\(\)\nValueError\n$
     497            valerr = r'\n    raise ValueError\(\)\nValueError\n
    498498            self.getPage("/error/page_method") 
    499             self.assertMatchesBody(valerr) 
    500              
     499            self.assertErrorPage(500, valerr) 
     500 
    501501            import cherrypy 
    502502            proto = cherrypy.config.get("server.protocolVersion", "HTTP/1.0") 
  • branches/filterorder/cherrypy/test/test_gzip_filter.py

    r605 r640  
    4646        'server.logToScreen': False, 
    4747        'server.environment': 'production', 
    48         'server.httpErrors': False, 
    4948        'server.showTracebacks': True, 
    5049        'gzipFilter.on': True, 
     
    8382            else: 
    8483                self.assertNoHeader('Content-Encoding') 
    85                 self.assertMatchesBody(r"IndexError\n$") 
     84                self.assertStatus('500 Internal error') 
     85                self.assertErrorPage(500, "IndexError\n") 
    8686        finally: 
    8787            helper.webtest.ignored_exceptions.pop() 
  • branches/filterorder/cherrypy/tutorial/tut10_http_errors.py

    r608 r640  
    1818            <a href="toggleTracebacks">Toggle tracebacks %s</a><br/><br/> 
    1919            <a href="/doesNotExist">Click me i'm a broken link!</a> 
     20            <br/> 
     21            <a href="/customMessage">Use a custom error message</a> 
    2022            <br/><br/> 
    2123            These errors are explicitly raised by the application. 
     
    4042        # raise an error based on the get query 
    4143        code = int(code) 
    42         raise cherrypy.HTTPStatusError(status = code) 
     44        raise cherrypy.HTTPError(status = code) 
    4345    error.exposed = True 
     46 
     47    def customMessage(self): 
     48        raise cherrypy.HTTPError(500, "Plain text message") 
     49    customMessage.exposed = True 
    4450 
    4551cherrypy.root = HTTPErrorDemo() 

Hosted by WebFaction

Log in as guest/cpguest to create tickets