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

Changeset 652

Show
Ignore:
Timestamp:
09/14/05 22:30:18
Author:
mikerobi
Message:

merged trunk (r651) back into mikerobi-experimental

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/mikerobi-experimental/cherrypy/_cpcgifs.py

    r634 r652  
    99        except ValueError, ex: 
    1010            if str(ex) == 'Maximum content length exceeded': 
    11                 print 50*'____\n' 
    1211                raise cherrypy.HTTPError(status=413) 
    1312            else: 
  • branches/mikerobi-experimental/cherrypy/_cperror.py

    r637 r652  
    2828 
    2929import urllib 
     30import os 
    3031 
    3132 
     
    174175 
    175176class HTTPError(Error): 
    176     """ Exception raised when the client has made an error in its request. 
     177    """ Exception used to return an HTTP error code to the client. 
    177178        This exception will automatically set the response status and body. 
    178179         
    179         A custom body can be pased to the init method in place of the standard error page. 
     180        A custom body can be pased to the init method in place of the 
     181        standard error page. 
    180182    """ 
    181183     
     
    184186        if status < 400 or status > 599: 
    185187            raise ValueError("status must be between 400 and 599.") 
    186          
    187         # these 4 lines might dissapear 
    188         import cherrypy 
    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 
     188          
     189        self.body = body 
     190     
     191    def set_response(self): 
     192        import cherrypy 
     193         
     194        # we now now have access to the traceback  
     195        statusString, defaultBody = cherrypy._cputil.getErrorStatusAndPage(self.status) 
     196         
     197        if self.body is _missing: 
     198            self.body = defaultBody 
     199            # try to look up a custom error page in the config map 
     200            # if there is no error page then use the pageGenerator 
     201             
     202            # The page generator is used because the init method is called  
     203            # before the exception is raised.  It is impossible to embed the 
     204            # traceback in the error page at this piont so we use the generator 
     205            # to render the error page at a later point 
     206             
     207            import cherrypy 
     208            # try and read the page from a file 
     209            # we use the default if the page can't be read 
     210            try: 
     211                errorPageFile = cherrypy.config.get('errorPage.%s' % status, '') 
     212                self.body = file(errorPageFile, 'r') 
     213            except: 
     214                # we have alread set the body 
     215                pass 
     216 
     217        cherrypy.response.status = statusString 
     218        cherrypy.response.body   = self.body 
    200219     
    201220    def __str__(self): 
    202         return self.statusString 
    203  
    204     def pageGenerator(self): 
    205         import cherrypy 
    206         yield cherrypy._cputil.getErrorStatusAndPage(self.status)[1] 
     221        import cherrypy 
     222        return cherrypy._cputil.getErrorStatusAndPage(self.status)[0] 
    207223 
    208224class NotFound(HTTPError): 
     
    212228        self.args = (path,) 
    213229        HTTPError.__init__(self, 404) 
     230 
     231    def __str__(self): 
     232        return self.args[0] 
  • branches/mikerobi-experimental/cherrypy/_cphttptools.py

    r634 r652  
    4545 
    4646import cherrypy 
    47 from cherrypy import _cputil, _cpcgifs, _cpwsgiserver 
     47from cherrypy import _cputil, _cpcgifs, _cpwsgiserver, _cperror 
    4848from cherrypy.lib import cptools 
    4949 
     
    286286                    applyFilters('beforeFinalize') 
    287287                    finalize() 
     288                except cherrypy.HTTPError, inst: 
     289                    # This includes NotFound 
     290                    inst.set_response() 
     291                    applyFilters('beforeFinalize') 
     292                    finalize() 
     293 
    288294            finally: 
    289295                applyFilters('onEndResource') 
     
    422428    try: 
    423429        applyFilters('beforeErrorResponse') 
    424          
     430        
    425431        # _cpOnError will probably change cherrypy.response.body. 
    426         # They may also change the headerMap, etc. 
     432        # It may also change the headerMap, etc. 
    427433        _cputil.getSpecialAttribute('_cpOnError')() 
    428434         
  • branches/mikerobi-experimental/cherrypy/_cputil.py

    r634 r652  
    210210    return "".join(traceback.format_exception(*exc)) 
    211211 
    212 def getErrorStatusAndPage(status, traceback = None): 
    213     statusString, message = _HTTPResponses[status] 
    214     statusString = '%d %s' % (status, statusString) 
    215      
    216     if traceback is None: 
    217         traceback = '' 
    218         # get the traceback from formatExc 
    219         developmentMode = (cherrypy.config.get('server.environment') == 'development') 
    220         if cherrypy.config.get('server.showTracebacks') or developmentMode: 
    221             traceback = formatExc() 
    222      
    223     page = _HTTPErrorTemplate(statusString, message, traceback, cherrypy.__version__) 
    224      
    225     return statusString, page 
    226  
    227     """formatExc(exc=None) -> exc (or sys.exc_info), formatted.""" 
    228     if exc is None: 
    229         exc = sys.exc_info() 
    230      
    231     if exc == (None, None, None): 
    232         return "" 
    233  
    234     return "".join(traceback.format_exception(*exc)) 
    235  
    236212def _cpOnError(): 
    237213    """ Default _cpOnError method """ 
     
    243219    response = cherrypy.response 
    244220     
    245     if isinstance(sys.exc_info()[1], cherrypy.HTTPError): 
    246         # status, body already set 
    247         pass 
    248     else: 
    249         response.status, response.body = getErrorStatusAndPage(500) 
     221    response.status, response.body = getErrorStatusAndPage(500) 
    250222     
    251223    if cherrypy.response.headerMap.has_key('Content-Encoding'): 
  • branches/mikerobi-experimental/cherrypy/_cpwsgiserver.py

    r634 r652  
    8383        self.rfile.close() 
    8484 
     85    def __iter__(self): 
     86        return self.rfile 
     87 
     88    def next(self): 
     89        data = self.rfile.next() 
     90        self.bytes_read += len(data) 
     91        self._check_length() 
     92##      Normally the next method must raise StopIteration when it 
     93##      fails but CP expects MaxSizeExceeded  
     94##        try: 
     95##            self._check_length() 
     96##        except: 
     97##            raise StopIteration() 
     98        return data 
    8599 
    86100class HTTPRequest(object): 
  • branches/mikerobi-experimental/cherrypy/lib/filter/sessionfilter.py

    r634 r652  
    5353 
    5454import datetime 
    55 import sha 
    5655import os 
    5756import pickle 
    5857import random 
     58import sha 
    5959import StringIO 
    6060import time 
     
    6464import basefilter 
    6565 
     66 
    6667class EmptyClass: 
    6768    """ An empty class """ 
    6869    pass 
    6970 
     71 
    7072class SessionDeadlockError(Exception): 
    71     """ Happens when a session can't acquire a lock after a 
    72         certain time 
    73     """ 
     73    """ The session could not acquire a lock after a certain time """ 
    7474    pass 
    7575 
     76 
    7677class SessionNotEnabledError(Exception): 
    77     """ Happens if user forgot to set sessionFilter.on to True """ 
     78    """ User forgot to set sessionFilter.on to True """ 
    7879    pass 
    7980 
     81 
    8082class SessionFilter(basefilter.BaseFilter): 
     83     
    8184    def beforeRequestBody(self): 
    8285        # We have to dynamically import cherrypy because Python can't handle 
     
    8487        global cherrypy 
    8588        import cherrypy 
     89        conf = cherrypy.config.get 
     90         
    8691        cherrypy.threadData._session = EmptyClass() 
    8792        sess = cherrypy.threadData._session 
     
    8994        # Dont enable session if sessionFilter is off or if this is a 
    9095        #   request for static data 
    91         if (not cherrypy.config.get('sessionFilter.on', False)) or \ 
    92                 cherrypy.config.get('staticFilter.on', False): 
     96        if ((not conf('sessionFilter.on', False)) 
     97              or conf('staticFilter.on', False)): 
    9398            sess.sessionStorage = None 
    9499            return 
    95  
     100         
    96101        sess.locked = False # Not locked by default 
    97  
     102         
    98103        # Read config options 
    99         sess.sessionTimeout = \ 
    100             cherrypy.config.get('sessionFilter.timeout', 60) 
    101  
    102         sess.sessionLocking = \ 
    103             cherrypy.config.get('sessionFilter.locking', 'implicit') 
    104  
    105         sess.onCreateSession = \ 
    106             cherrypy.config.get('sessionFilter.onCreateSession', 
    107                 lambda data: None) 
    108  
    109         sess.onDeleteSession = \ 
    110             cherrypy.config.get('sessionFilter.onDeleteSession', 
    111                 lambda data: None) 
    112  
    113         cleanUpDelay = \ 
    114             cherrypy.config.get('sessionFilter.cleanUpDelay', 5) 
    115  
    116         cookieName = \ 
    117             cherrypy.config.get('sessionFilter.cookieName', 'sessionID') 
    118  
    119         sess.deadlockTimeout = \ 
    120             cherrypy.config.get('sessionFilter.deadlockTimeout', 30) 
    121  
    122         storage = cherrypy.config.get('sessionFilter.storageType', 'Ram') 
     104        sess.sessionTimeout = conf('sessionFilter.timeout', 60) 
     105        sess.sessionLocking = conf('sessionFilter.locking', 'implicit') 
     106        sess.onCreateSession = conf('sessionFilter.onCreateSession', 
     107                                    lambda data: None) 
     108        sess.onDeleteSession = conf('sessionFilter.onDeleteSession', 
     109                                    lambda data: None) 
     110         
     111        cleanUpDelay = conf('sessionFilter.cleanUpDelay', 5) 
     112        cleanUpDelay = datetime.timedelta(seconds = cleanUpDelay * 60) 
     113         
     114        cookieName = conf('sessionFilter.cookieName', 'sessionID') 
     115        sess.deadlockTimeout = conf('sessionFilter.deadlockTimeout', 30) 
     116         
     117        storage = conf('sessionFilter.storageType', 'Ram') 
    123118        storage = storage[0].upper() + storage[1:] 
    124  
     119         
    125120        # People can set their own custom class 
    126121        #   through sessionFilter.storageClass 
    127         sess.sessionStorage = \ 
    128             cherrypy.config.get('sessionFilter.storageClass', None) 
     122        sess.sessionStorage = conf('sessionFilter.storageClass', None) 
    129123        if sess.sessionStorage is None: 
    130124            sess.sessionStorage = globals()[storage + 'Storage']() 
    131  
     125         
    132126        # Check if we need to clean up old sessions 
    133         if cherrypy._sessionLastCleanUpTime + \ 
    134                 datetime.timedelta(seconds = cleanUpDelay * 60) < now: 
     127        if cherrypy._sessionLastCleanUpTime + cleanUpDelay < now: 
    135128            sess.sessionStorage.cleanUp() 
    136  
     129         
    137130        # Check if request came with a session ID 
    138131        if cookieName in cherrypy.request.simpleCookie: 
    139132            # It did: we try to load the session data 
    140133            sess.sessionID = cherrypy.request.simpleCookie[cookieName].value 
     134             
    141135            # If using implicit locking, acquire lock 
    142136            if sess.sessionLocking == 'implicit': 
    143137                sess.sessionData = {'_id': sess.sessionID} 
    144138                sess.sessionStorage.acquireLock() 
     139             
    145140            data = sess.sessionStorage.load(sess.sessionID) 
    146141            # data is either None or a tuple (sessionData, expirationTime) 
    147142            if data is None or data[1] < now: 
    148                 # Expired session: flush session data (but keep the same 
    149                 # sessionID) 
     143                # Expired session: 
     144                # flush session data (but keep the same sessionID) 
    150145                sess.sessionData = {'_id': sess.sessionID} 
    151146            else: 
     
    157152            sess.onCreateSession(sess.sessionData) 
    158153        # Set response cookie 
    159         cherrypy.response.simpleCookie[cookieName] = sess.sessionID 
    160         cherrypy.response.simpleCookie[cookieName]['path'] = '/' 
    161         cherrypy.response.simpleCookie[cookieName]['max-age'] = \ 
    162             sess.sessionTimeout * 60 
    163         cherrypy.response.simpleCookie[cookieName]['version'] = 1 
    164  
     154        cookie = cherrypy.response.simpleCookie 
     155        cookie[cookieName] = sess.sessionID 
     156        cookie[cookieName]['path'] = '/' 
     157        cookie[cookieName]['max-age'] = sess.sessionTimeout * 60 
     158        cookie[cookieName]['version'] = 1 
     159     
    165160    def beforeFinalize(self): 
    166         def returnBodyAndSaveData(body, sess): 
     161        def saveData(body, sess): 
    167162            try: 
    168163                # If the body is a generator, we have to save the data 
     
    171166                    for line in body: 
    172167                        yield line 
    173  
     168                 
    174169                # Save session data 
    175                 expirationTime = datetime.datetime.now() + \ 
    176                         datetime.timedelta(seconds = sess.sessionTimeout * 60) 
    177                 sess.sessionStorage.save( 
    178                         sess.sessionID, sess.sessionData, expirationTime) 
     170                t = datetime.timedelta(seconds = sess.sessionTimeout * 60) 
     171                expirationTime = datetime.datetime.now() + t 
     172                sess.sessionStorage.save(sess.sessionID, sess.sessionData, 
     173                                        expirationTime) 
    179174                if sess.locked: 
    180175                    # Always release the lock if the user didn't release it 
    181176                    sess.sessionStorage.releaseLock() 
    182  
     177                 
    183178                # If the body is not a generator, we save the data 
    184179                #   before the body is returned 
     
    191186                raise 
    192187            self._clean(sess) 
    193  
     188         
    194189        sess = cherrypy.threadData._session 
    195190        if not sess.sessionStorage: 
    196191            # Sessions are not enabled: do nothing 
    197192            return 
    198  
     193         
    199194        # Make a wrapper around the body in order to save the session 
    200195        #   either before or after the body is returned 
    201         cherrypy.response.body = \ 
    202             returnBodyAndSaveData(cherrypy.response.body, sess) 
    203  
     196        cherrypy.response.body = saveData(cherrypy.response.body, sess) 
     197     
    204198    def afterErrorResponse(self): 
    205199        sess = cherrypy.threadData._session 
     
    208202            return 
    209203        self._clean(sess) 
    210  
     204     
    211205    def _clean(self, sess): 
    212206        if getattr(sess, 'locked', None): 
     
    221215class RamStorage: 
    222216    """ Implementation of the RAM backend for sessions """ 
     217     
    223218    def load(self, id): 
    224219        return cherrypy._sessionDataHolder.get(id) 
     220     
    225221    def save(self, id, data, expirationTime): 
    226222        cherrypy._sessionDataHolder[id] = (data, expirationTime) 
     223     
    227224    def acquireLock(self): 
    228225        sess = cherrypy.threadData._session 
     
    239236                raise SessionDeadlockError() 
    240237        sess.locked = True 
     238     
    241239    def releaseLock(self): 
    242240        sess = cherrypy.threadData._session 
     
    244242        cherrypy._sessionLockDict[id].release() 
    245243        sess.locked = False 
     244     
    246245    def cleanUp(self): 
    247246        sess = cherrypy.threadData._session 
     
    255254            del cherrypy._sessionDataHolder[id] 
    256255 
     256 
    257257class FileStorage: 
    258258    """ Implementation of the File backend for sessions """ 
     259     
    259260    SESSION_PREFIX = 'session-' 
    260261    LOCK_SUFFIX = '.lock' 
     262     
    261263    def load(self, id): 
    262264        filePath = self._getFilePath(id) 
     
    268270        except IOError: 
    269271            return None 
     272     
    270273    def save(self, id, data, expirationTime): 
    271274        filePath = self._getFilePath(id) 
     
    273276        pickle.dump((data, expirationTime), f) 
    274277        f.close() 
     278     
    275279    def acquireLock(self): 
    276280        sess = cherrypy.threadData._session 
     
    279283        self._lockFile(lockFilePath) 
    280284        sess.locked = True 
    281  
     285     
    282286    def releaseLock(self): 
    283287        sess = cherrypy.threadData._session 
     
    286290        self._unlockFile(lockFilePath) 
    287291        sess.locked = False 
    288  
     292     
    289293    def cleanUp(self): 
    290294        sess = cherrypy.threadData._session 
     
    294298        #   and lock files 
    295299        for fname in os.listdir(storagePath): 
    296             if fname.startswith(self.SESSION_PREFIX) and \ 
    297                         (not fname.endswith(self.LOCK_SUFFIX)): 
     300            if (fname.startswith(self.SESSION_PREFIX) 
     301                and not fname.endswith(self.LOCK_SUFFIX)): 
    298302                # We have a session file: lock it, load it and check 
    299303                #   if it's expired 
     
    303307                try: 
    304308                    f = open(filePath, "rb") 
    305                     (data, expirationTime) = pickle.load(f) 
     309                    data, expirationTime = pickle.load(f) 
    306310                    f.close() 
    307311                    if expirationTime < now: 
     
    314318                    pass 
    315319                self._unlockFile(lockFilePath) 
    316  
     320     
    317321    def _getFilePath(self, id): 
    318322        storagePath = cherrypy.config.get('sessionFilter.storagePath') 
     
    320324        filePath = os.path.join(storagePath, fileName) 
    321325        return filePath 
    322  
     326     
    323327    def _lockFile(self, path): 
    324328        sess = cherrypy.threadData._session 
     
    330334                if time.time() - startTime > sess.deadlockTimeout: 
    331335                    raise SessionDeadlockError() 
     336                time.sleep(0.5) 
    332337            else: 
    333338                os.close(lockfd)  
    334339                break 
     340     
    335341    def _unlockFile(self, path): 
    336342        os.unlink(path) 
     343 
    337344 
    338345class PostgreSQLStorage: 
     
    346353            ) 
    347354    """ 
     355     
    348356    def __init__(self): 
    349357        self.db = cherrypy.config.get('sessionFilter.getDB')() 
    350358        self.cursor = self.db.cursor() 
     359     
    351360    def __del__(self): 
    352361        if self.cursor: 
    353362            self.cursor.close() 
    354363        self.db.commit() 
     364     
    355365    def load(self, id): 
    356366        # Select session data from table 
     
    366376        data = pickle.load(f) 
    367377        return (data, expirationTime) 
     378     
    368379    def save(self, id, data, expirationTime): 
    369380        # Try to delete session if it was already there 
     
    378389            'insert into session (id, data, expiration_time) values (%s, %s, %s)', 
    379390            (id, f.getvalue(), expirationTime)) 
    380  
     391     
    381392    def acquireLock(self): 
    382393        # We use the "for update" clause to lock the row 
     
    384395            'select id from session where id=%s for update', 
    385396            (cherrypy.session['_id'],)) 
    386  
     397     
    387398    def releaseLock(self): 
    388399        # We just close the cursor and that will remove the lock 
     
    390401        self.cursor.close() 
    391402        self.cursor = None 
     403     
    392404    def cleanUp(self): 
    393405        sess = cherrypy.threadData._session 
     
    403415            (now,)) 
    404416 
     417 
    405418def generateSessionID(): 
    406         """ Return a new sessionID """ 
    407         return sha.new('%s' % random.random()).hexdigest() 
     419    """ Return a new sessionID """ 
     420    return sha.new('%s' % random.random()).hexdigest() 
     421 
    408422 
    409423# Users access sessions through cherrypy.session, but we want this 
     
    412426#   cherrypy.threadData._session.sessionData 
    413427class SessionWrapper: 
     428     
    414429    def __getattr__(self, name): 
    415430        sess = cherrypy.threadData._session 
     
    423438            return sess.sessionStorage.releaseLock 
    424439        return getattr(sess.sessionData, name) 
     440 
  • branches/mikerobi-experimental/cherrypy/test/test.py

    r615 r652  
    124124        print """CherryPy Test Program 
    125125    Usage: 
    126         test.py --server --1.1 --cover --basedir=path --profile --test 
     126        test.py --servers* --1.1 --cover --basedir=path --profile --tests** 
     127         
    127128    """ 
    128         print '    servers:' 
     129        print '    * servers:' 
    129130        s = [(val, name) for name, val in self.available_servers.iteritems()] 
    130131        s.sort() 
    131132        for val, name in s: 
    132133            if name == self.default_server: 
    133                 print '        ', name, '(default)' 
     134                print '        --' + name, '(default)' 
    134135            else: 
    135                 print '        ', name 
    136          
    137         print """        all (runs all servers in order) 
    138      
    139     1.1: use HTTP/1.1 servers instead of default HTTP/1.0 
    140      
    141     cover: turn on code-coverage tool 
    142     basedir=path: display coverage stats for some path other than cherrypy. 
    143      
    144     profile: turn on profiling tool 
     136                print '        --' + name 
     137         
     138        print """        --all (runs all servers in order) 
     139     
     140    --1.1: use HTTP/1.1 servers instead of default HTTP/1.0 
     141     
     142    --cover: turn on code-coverage tool 
     143    --basedir=path: display coverage stats for some path other than cherrypy. 
     144     
     145    --profile: turn on profiling tool 
    145146    """ 
    146147         
    147         print '    tests:' 
     148        print '    ** tests:' 
    148149        for name in self.available_tests: 
    149             print '        ', name 
     150            print '        --' + name 
    150151     
    151152    def start_coverage(self): 
  • branches/mikerobi-experimental/cherrypy/test/test_core.py

    r634 r652  
    639639        self.assertHeader('Set-Cookie', 'Last=Piranha;') 
    640640 
    641     def __testMaxRequestSize(self): 
     641    def testMaxRequestSize(self): 
    642642        self.getPage("/maxrequestsize/index") 
    643643        self.assertBody("OK") 
    644         cherrypy.config.update({'server.maxRequestHeaderSize': 10}) 
    645         self.getPage("/maxrequestsize/index") 
    646         self.assertStatus("413 Request Entity Too Large") 
    647         self.assertBody("Request Entity Too Large") 
    648         cherrypy.config.update({'server.maxRequestHeaderSize': 0}) 
    649  
     644         
     645        if cherrypy._httpserver.__class__.__name__ == "WSGIServer": 
     646            cherrypy.config.update({'server.maxRequestHeaderSize': 10}) 
     647            self.getPage("/maxrequestsize/index") 
     648            self.assertStatus("413 Request Entity Too Large") 
     649            self.assertBody("Request Entity Too Large") 
     650            cherrypy.config.update({'server.maxRequestHeaderSize': 0}) 
     651         
    650652        # Test upload 
    651653        h = [("Content-type", "multipart/form-data; boundary=x"), 
     
    660662        self.getPage('/maxrequestsize/upload', h, "POST", b) 
    661663        self.assertBody('Size: 5') 
    662         cherrypy.config.update({ 
    663             '/maxrequestsize': {'server.maxRequestBodySize': 3}}) 
    664         self.getPage('/maxrequestsize/upload', h, "POST", b) 
    665         self.assertStatus("413 Request Entity Too Large") 
    666         self.assertInBody("Request Entity Too Large") 
     664         
     665        if cherrypy._httpserver.__class__.__name__ == "WSGIServer": 
     666            cherrypy.config.update({ 
     667                '/maxrequestsize': {'server.maxRequestBodySize': 3}}) 
     668            self.getPage('/maxrequestsize/upload', h, "POST", b) 
     669            self.assertStatus("413 Request Entity Too Large") 
     670            self.assertInBody("Request Entity Too Large") 
    667671 
    668672if __name__ == '__main__': 
  • branches/mikerobi-experimental/cherrypy/test/webtest.py

    r637 r652  
    286286                msg = 'No match for %s in body' % `pattern` 
    287287            self._handlewebError(msg) 
    288     
     288 
     289 
    289290 
    290291def cleanHeaders(headers, method, body, host, port): 
  • branches/mikerobi-experimental/cherrypy/tutorial/tut10_http_errors.py

    r634 r652  
    33import cherrypy 
    44 
     5# we want to customize 403 errors 
     6customErrors = { 
     7                 'errorPage.403' : "custom_error.html" 
     8               } 
     9 
     10cherrypy.config.update({'/' : customErrors}) 
    511 
    612class HTTPErrorDemo(object): 
     
    1622        return """ 
    1723        <html><body> 
    18             <a href="toggleTracebacks">Toggle tracebacks %s</a><br/><br/
     24            <h2><a href="toggleTracebacks">Toggle tracebacks %s</a><br/><br/></h2
    1925            <a href="/doesNotExist">Click me i'm a broken link!</a> 
    20             <br/> 
    21             <a href="/customMessage">Use a custom error message</a> 
     26            <br/><br/> 
     27            <a href="/error?code=403">Use a custom an error page from a file.</a> 
    2228            <br/><br/> 
    2329            These errors are explicitly raised by the application. 
     
    2632            <a href="/error?code=402">402</a> 
    2733            <a href="/error?code=500">500</a> 
     34            <br/><br/> 
     35            <a href="/bodyArg">You can also set the response body when you raise an error</a> 
    2836        </body></html> 
    2937        """ % trace 
     
    4553    error.exposed = True 
    4654 
    47     def customMessage(self): 
    48         raise cherrypy.HTTPError(500, "Plain text message") 
    49     customMessage.exposed = True 
     55    def bodyArg(self): 
     56        message = """ If you construct a HTTPError wiht body argument, the body argument 
     57                      will overide any default or custom error page. 
     58                  """ 
     59        raise cherrypy.HTTPError(403, body = message) 
     60    bodyArg.exposed = True 
    5061 
    5162cherrypy.root = HTTPErrorDemo() 
  • branches/mikerobi-experimental/cherrypy/tutorial/tutorial.conf

    r629 r652  
    22server.socketPort = 8080 
    33server.threadPool = 10 
    4 #server.environment = "production" 
    5 #server.showTracebacks = True 
     4server.environment = "production" 
     5# server.showTracebacks = True 
    66# server.logToScreen = False 
  • branches/mikerobi-experimental/docs/book/xml/apireference.xml

    r615 r652  
    299299      <listitem> 
    300300        <section> 
    301             <title>cherrypy.HTTPStatusError</title> 
     301            <title>cherrypy.HTTPError</title> 
    302302            <para> 
    303303                This exception can be used to automatically send a response  
  • branches/mikerobi-experimental/docs/book/xml/appdeveloperreference.xml

    r637 r652  
    1717  <xi:include href="staticcontenthandling.xml" /> 
    1818  <xi:include href="fileuploadbehavior.xml" /> 
     19    <xi:include href="errorhandling.xml" /> 
    1920</section> 
  • branches/mikerobi-experimental/setup.py

    r615 r652  
    4242            'cherrypy/tutorial/tutorial.conf', 
    4343            'cherrypy/tutorial/README.txt', 
     44            'cherrypy/tutorial/ReturnVsYield.pdf', 
     45            'cherrypy/tutorial/custom_error.html', 
    4446        ] 
    4547    ), 
     
    8183if __name__ == "__main__": 
    8284    main() 
     85 

Hosted by WebFaction

Log in as guest/cpguest to create tickets