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

Errors and Exceptions

CherryPy provides (and uses) exceptions for declaring that the HTTP response should be a status other than the default "200 OK".

HTTPError

This exception can be used to automatically send a response using a http status code, with an appropriate error page. HTTPError takes an optional 'status' argument (which must be between 400 and 599); it defaults to 500 ("Internal Server Error"). It also takes an optional 'message' argument, which will be returned in the response body. See RFC 2616 for a complete list of available error codes and when to use them.

NotFound

This exception is raised when CherryPy is unable to map a requested path to an internal method. It's equivalent to raising HTTPError("404 Not Found").

HTTPRedirect

This exception will force a HTTP redirect to the URL or URL's you give it.

There are multiple types of redirect, from which you can select via the 'status' argument. If you do not provide a 'status' arg, it defaults to 303 (or 302 if responding with HTTP/1.0).

Redirecting POST

When you GET a resource and are redirected by the server to another Location, there's generally no problem since GET is both a "safe method" (there should be no side-effects) and an "idempotent method" (multiple calls are no different than a single call). POST, however, is neither safe nor idempotent--if you charge a credit card, you don't want to be charged twice by a redirect!

For this reason, none of the 3xx responses permit a user-agent (browser) to resubmit a POST on redirection without first confirming the action with the user:

300Multiple ChoicesConfirm with the user
301Moved PermanentlyConfirm with the user
302Found (Object moved temporarily)Confirm with the user
303See OtherGET the new URI--no confirmation
304Not modified(for conditional GET only--POST should not raise this error)
305Use ProxyConfirm with the user
307Temporary RedirectConfirm with the user

However, browsers have historically implemented these restrictions poorly; in particular, many browsers do not force the user to confirm 301, 302 or 307 when redirecting POST. For this reason, CherryPy defaults to HTTPRedirect(303), which most user-agents appear to have implemented correctly. Therefore, if you raise HTTPRedirect(new_uri) for a POST request, the user-agent will most likely attempt to GET the new URI (without asking for confirmation from the user). We realize this is confusing for developers; but it's the safest thing we could do. You are of course free to raise HTTPRedirect(uri, status=302) or any other 3xx status if you know what you're doing, but given the environment, we couldn't let any of those be the default.

InternalRedirect

This exception will redirect processing to another path within the site (without informing the client). Provide the new path as an argument when raising the exception. Provide any params in the querystring for the new URL.

Custom Error Handling

http://www.cherrypy.org/attachment/wiki/ErrorsAndExceptions/cperrors.gif?format=raw

Anticipated HTTP responses

The 'error_page' config namespace can be used to provide custom HTML output for expected responses (like 404 Not Found). Supply a filename from which the output will be read. The contents will be interpolated with the values %(status)s, %(message)s, %(traceback)s, and %(version)s using plain old Python string formatting.

_cp_config = {'error_page.404': os.path.join(localDir, "static/index.html")}

Beginning in version 3.1, you may also provide a function or other callable as an error_page entry. It will be passed the same status, message, traceback and version arguments that are interpolated into templates:

def error_page_402(status, message, traceback, version):
    return "Error %s - Well, I'm very sorry but you haven't paid!" % status
cherrypy.config.update({'error_page.402': error_page_402})

Also in 3.1, in addition to the numbered error codes, you may also supply "error_page.default" to handle all codes which do not have their own error_page entry.

Unanticipated errors

CherryPy also has a generic error handling mechanism: whenever an unanticipated error occurs in your code, it will call request.error_response to set the response status, headers, and body. By default, this is the same output as HTTPError(500). If you want to provide some other behavior, you generally replace request.error_response.

Here is some sample code that shows how to display a custom error message and send an e-mail containing the error:

from cherrypy import _cperror

def handle_error():
    cherrypy.response.status = 500
    cherrypy.response.body = ["<html><body>Sorry, an error occured</body></html>"]
    sendMail('error@domain.com', 'Error in your web app', _cperror.format_exc())

class Root:
    _cp_config = {'request.error_response': handle_error}

Note that you have to explicitly set cherrypy.response.body and not simply return an error message as a result.

Older versions

2.2

CherryPy used magic "_cpOnError" name for handlers. For instance:

class MySection:

    def _cpOnError(self):
        # Handle all errors that happen under http://domain/mySection/*

class Root:
    def _cpOnError(self):
        # Handle all other errors
cpg.root = Root()
cpg.root.mySection = MySection()

In CherryPy 2, _cpOnError was used for both expected and unexpected errors. Here is a sample that shows how to trap "NotFound" errors and return a 404 code:

from cherrypy import cperror
def _cpOnError(self):
    try:
        raise
    except cperror.NotFound:
        cpg.response.headerMap['Status'] = '404 Not Found'
        cpg.response.body = ['Page not found']
    except:
        pass # Handle other errors here

Attachments

Hosted by WebFaction

Log in as guest/cpguest to create tickets