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

Tools

Here, we discuss the idea of Tools and what Tools CherryPy supplies for you. To read about making your own Tools, see CustomTools.

Using tools

Tools are a great way to package up behavior that happens outside your page handlers. For example, you can add static directory serving with the builtin staticdir tool with just a few lines in your config file:

[/docroot]
tools.staticdir.on: True
tools.staticdir.root: "/path/to/app"
tools.staticdir.dir: 'static'

This turns on the staticdir tool for all URLs that start with "/docroot". You can also enable and configure tools per controller or per handler using _cp_config:

class docroot(object):

    _cp_config = {'tools.staticdir.on': True,
                  'tools.staticdir.root: "/path/to/app",
                  'tools.staticdir.dir': 'static'}

But we can do even better by using the builtin decorator support that all Tools have:

class docroot(object):

    @tools.staticdir(root="/path/to/app", dir='static')
    def page(self):
       ...

...and in this case, we can do even better because tools.staticdir is a 'HandlerTool', and therefore can be used directly as a page handler:

class docroot(object):

    static = tools.staticdir.handler(
                 section='static', root="/path/to/app", dir='static')

Finally, you can use (most) Tools directly, by calling the function they wrap. They expose this via the 'callable' attribute:

def page(self):
    tools.response_headers.callable([('Content-Language', 'fr')])
    return "Bonjour, le Monde!"
page.exposed = True

Because the underlying function is wrapped in a tool, you need to call help(tools.whatevertool.callable) if you want the docstring for it. Using help(tools.whatevertool) will give you help on how to use it as a Tool (for example, as a decorator).

Tools also are also inspectable automatically. They expose their own arguments as attributes:

>>> dir(cherrypy.tools.session_auth)
[..., 'anonymous', 'callable', 'check_username_and_password',
'do_check', 'do_login', 'do_logout', 'handler', 'login_screen',
'on_check', 'on_login', 'on_logout', 'run', 'session_key']

This makes IDE calltips especially useful, even when writing config files!

Builtin tools

tools.accept

A tool for verifying that the client is willing to accept the Content-Type of the response.

tools.accept.media, if provided, should be the Content-Type value (as a string) or values (as a list or tuple of strings) which the current request can emit. The client's acceptable media ranges (as declared in the Accept request header) will be matched in order to these Content-Type values; the first such string is returned. That is, the return value will always be one of the strings provided in the 'media' arg (or None if 'media' is None).

The return value doesn't mean anything when used as a Tool, but you can call tools.accept.callable(media) directly to dispatch based on the client's preferred Content-Type:

def select(self):
    mtype = tools.accept.callable(['text/html', 'text/plain'])
    if mtype == 'text/html':
        return "<h2>Page Title</h2>"
    else:
        return "PAGE TITLE"
select.exposed = True

Regardless of whether you call it directly or just turn on the Tool, if no match is found, then HTTPError 406 (Not Acceptable) is raised. Note that most web browsers send */* as a (low-quality) acceptable media range, which should match any Content-Type. In addition, "...if no Accept header field is present, then it is assumed that the client accepts all media types."

tools.basic_auth

A tool for doing basic authentication. It takes a "realm" setting (a string) and a "users" dict of {username: password} pairs (or a callable which returns that dict). If authentication is successful, cherrypy.request.login will contain the user name. If authentication fails, 401 Unauthorized is raised, the 'WWW-Authenticate' response header is set, and cherrypy.request.login is set to False.

tools.caching

This tool tries to be an (in-process) HTTP/1.1-compliant cache. It's not quite there yet, but it's probably good enough for most sites.

In general, GET responses are cached (along with selecting headers) and, if another request arrives for the same resource, the caching Tool will return 304 Not Modified if possible, or serve the cached response otherwise. It also sets request.cached to True if serving a cached representation, and sets request.cacheable to False (so it doesn't get cached again).

If POST, PUT, or DELETE requests are made for a cached resource, they invalidate (delete) any cached response.

For more information see Caching.

tools.decode

Use this tool to decode cherrypy.request.params (GET and POST query arguments) from on-the-wire strings to Unicode. If you think you know exactly what encoding the client used, and want to be strict about it, set tools.decode.encoding; otherwise, set tools.decode.default_encoding as needed (it defaults to UTF-8). Note that, if the encodings you supply fail, the tool will fall back to decoding from ISO-8859-1 (as the HTTP spec requires).

tools.digest_auth

A tool for doing Digest authentication (RFC 2617). It takes a "realm" setting (a string) and a "users" dict of {username: password} pairs (or a callable which returns that dict). If authentication is successful, cherrypy.request.login will contain the user name. If authentication fails, 401 Unauthorized is raised, the 'WWW-Authenticate' response header is set, and cherrypy.request.login is set to False.

tools.encode

Encode the outgoing response body, from Unicode to an encoded string. If you specify tools.encode.encoding, the tool will error if the response cannot be encoded with it. Otherwise, the tool will use the 'Accept-Charset' request header to attempt to provide suitable encodings, usually attempting utf-8 if the client doesn't specify a charset, but following RFC 2616 and trying ISO-8859-1 if the client sent an empty 'Accept-Charset' header.

tools.err_redirect

Turn this tool on to redirect all unhandled errors to a different page. Supply the new URL via tools.err_redirect.url. By default, this raises InternalRedirect?. To use HTTPRedirect, set tools.err_redirect.internal to False.

tools.etags

This tool validates the current ETag response header against If-Match and If-None-Match headers, and raises "304 Not Modified" or "412 Precondition Failed" as needed. If tools.etags.autotags is True, an ETag response-header value will be provided from an MD5 hash of the response body (unless some other code has already provided an ETag header). If False (the default), the ETag will not be automatic--your code must provide it before this tool is called (in the before_finalize phase).

tools.expires

A tool for influencing cache mechanisms using the 'Expires' header.

tools.expires.secs must be either an int or a datetime.timedelta, and indicates the number of seconds between response.time and when the response should expire. The 'Expires' header will be set to (response.time + secs). If zero (the default), the following "cache prevention" headers are also set:

'Pragma': 'no-cache'
'Cache-Control': 'no-cache'

If tools.expires.force is False (the default), the following headers are checked: 'Etag', 'Last-Modified', 'Age', 'Expires'. If any are already present, none of the above response headers are set.

tools.flatten

Wraps response.body in a generator that recursively iterates over body. This allows cherrypy.response.body to consist of 'nested generators'; that is, a set of generators that yield generators.

tools.gzip

This tool gzips (compresses) the response body if possible, and sets the 'Content-Encoding' and 'Vary' headers appropriately. The client must send an 'Accept-Encoding' request header that prefers 'gzip' or 'x-gzip'. If a suitable encoding cannot be produced, then 406 Not Acceptable is raised.

tools.ignore_headers

Deletes request headers whose field names are included in tools.ignore_headers.headers. This is a useful tool for working behind certain HTTP servers and proxies; for example, Apache duplicates the work that CP does for 'Range' headers, and will doubly-truncate the response.

tools.log_headers

When enabled, the headers of every request will be sent to CherryPy's log when an unanticipated error occurs.

tools.log_tracebacks

When turned on, all unhandled errors will have their tracebacks sent to CherryPy's log.

tools.nsgmls

A tool for validating the response according to NSGMLS. If errors are encountered, the response body is replaced with the error output.

tools.proxy

Example:

tools.proxy(base=None, local='X-Forwarded-Host', 
            remote='X-Forwarded-For', scheme='X-Forwarded-Proto')

This changes the base URL (scheme://host[:port][/path]), and is most useful when running a CP server behind Apache or some other webserver. For example, Apache may receive a Request-URI of http://www.example.com/app/page, but rewrites it to http://localhost:8080/page before forwarding the request to CherryPy. This tool tells CherryPy how to get the original URI.

tools.proxy.local defines the request header which will be used to auto-fill the new request.base. If you want the new request.base to include path info (not just the host), you must explicitly set base to the full base path, and ALSO set tools.proxy.local to "" (empty string), so that the X-Forwarded-Host request header (which never includes path info) does not override it.

New in CP 3: cherrypy.request.remote.ip (the IP address of the client) will be rewritten if the header specified by tools.proxy.remote is valid. By default, 'remote' is set to 'X-Forwarded-For'. If you do not want to rewrite remote.ip, set the 'remote' arg to an empty string.

Example config for a mod_python site running at http://my.vhost/apps/app/:

[/]
tools.proxy.on: True
tools.proxy.base: "http://my.vhost/apps/app/"

tools.redirect

This one is so simple we might as well show the whole function instead of just the signature:

def redirect(url='', internal=True):
    """Raise InternalRedirect or HTTPRedirect to the given url."""
    if internal:
        raise cherrypy.InternalRedirect(url)
    else:
        raise cherrypy.HTTPRedirect(url)

Raises InternalRedirect? or HTTPRedirect.

  • url: the new URL to which to redirect.
  • internal: True (the default) to perform an internal redirect; CherryPy loops and starts a new request completely within the same thread/process. False to perform an external redirect; the client (browser) will be told to fetch the new URL instead. If the new URL is located on a different host or domain, an external redirect must be used.

tools.referer

def referer(pattern, accept=True, accept_missing=False, error=403, message=):

Raises HTTPError if the client's Referer header does not pass our test.

  • pattern: a regular expression pattern to test against the Referer.
  • accept: if True (the default), the Referer must match the pattern; if False, the Referer must NOT match the pattern.
  • accept_missing: if True, permit requests with no Referer header. Defaults to False.
  • error: the HTTP error code to return to the client on failure. Defaults to 403 Forbidden.
  • message: a string to include in the response body on failure. Defaults to 'Forbidden Referer header.'

tools.response_headers

Use this tool to set static response headers. Here's the complete source code for the Tool, to show you again how easy it can be to make your own tools:

def response_headers(headers=None):
    """Set headers on the response."""
    for name, value in (headers or []):
        cherrypy.response.headers[name] = value
cherrypy.tools.response_headers = cherrypy.Tool('on_start_resource', response_headers)

tools.session_auth

tools.staticdir

Serves static resources from the given (.root +) tools.staticdir.dir. See StaticContent.

tools.staticfile

Serves a static resource from the given (.root +) tools.staticfile.filename. See StaticContent.

tools.sessions

See CherryPySessions.

tools.tidy

A tool for validating the response according to HTML Tidy. If errors are encountered, the response body is replaced with the error output.

If either tools.tidy.indent or .wrap are specified, then response.body will be set to the output of tidy. If .warnings is True (the default), the response body will contain them. Otherwise, only errors will change the body. Note that we use the standalone Tidy tool rather than the python mxTidy module. This is because this module does not seem to be stable and it crashes on some HTML pages (which means that the server would also crash). You must set tools.tidy.tidy_path to the location of the Tidy executable on your system. You must also provide a value for temp_dir, the location in which to write the temporary files for shuttling output to the Tidy executable.

tools.trailing_slash

A tool that lets you control whether URL's with a missing or extra trailing slash should raise HTTPRedirect. It's on by default, with these settings:

tools.trailing_slash.on = True
tools.trailing_slash.missing = True
tools.trailing_slash.extra = False

That is, if a trailing slash is missing for an index handler, HTTPRedirect is raised. But if a non-index handler has an extra slash, it's not redirected by default.

tools.xmlrpc

Don't use this directly. Instead, it's used by the XMLRPCController. To use it, have your controllers subclass cherrypy._cptools.XMLRPCController. You can also supply the following optional config entries:

  • tools.xmlrpc.encoding: 'utf-8'
  • tools.xmlrpc.allow_none: 0

XML-RPC is a rather discontinuous layer over HTTP; dispatching to the appropriate handler must first be performed according to the URL, and then a second dispatch step must take place according to the RPC method specified in the request body. It also allows a superfluous "/RPC2" prefix in the URL, supplies its own handler args in the body, and requires a 200 OK "Fault" response instead of 404 when the desired method is not found. Therefore, XML-RPC cannot be implemented for CherryPy via a Tool alone. The Controller acts as the dispatch target for the first half (based on the URL); it then reads the RPC method from the request body and does its own second dispatch step based on that method. It also reads body params, and returns a Fault on error. The XMLRPCDispatcher strips any /RPC2 prefix; if you aren't using /RPC2 in your URL's, you can safely skip turning on the XMLRPCDispatcher. Otherwise, you need to use declare it in config:

[global]
request.dispatch: cherrypy.dispatch.XMLRPCDispatcher()

Hosted by WebFaction

Log in as guest/cpguest to create tickets