Table of Contents
List of Figures
List of Examples
Table of Contents
CherryPy is a pythonic, object-oriented web development framework. It provides the foundation over which complex web-based applications can be written, with little or no knowledge of the underlying protocols. CherryPy allows developers to build web applications in much the same way they would build any other object-oriented Python program. This usually results in smaller source code developed in less time.
CherryPy does its best to stay out of the way between the programmer and the problem. CherryPy applications are usually very simple. It works out of the box; default behavior is sensible enough to allow use without extensive setup or customization. The embedded web server allows one to deploy web applications anywhere Python is installed. In short, CherryPy is as pythonic as it gets.
Table of Contents
Abstract
Since CherryPy is pure Python and has no dependencies, obtaining and installing it is a snap. You can install using a release package, or by using Subversion.
A "release package" is an official stable release of CherryPy. It means that the main features and issues that were decided to be integrated and fixed for a particular milestone, have been.
The latest package is available from the sourceforge repository of the CherryPy project. You need to pick up the latest version of the package.
Installing CherryPy from a release package will take three steps only. Type the following commands :
tar {zxvf} {CherryPy-2.1.0.tar.gz}
Which will create the CherryPy-2.1.0 directory.
cd {CherryPy-2.1.0}
Then issue the following command (if you are under Unix or Linux, you should be root):
python {setup.py} {install}
The CherryPy project uses Subversion to control access to its source code. Getting CherryPy from the latest changeset is sometimes required because a bugfix or a feature is only available from it. Keep in mind that subversion code is subject to change on a regular basis; therefore, only use it if you know what you are doing.
To get the latest source code from the subversion repository, you first need to install a SVN client. On Microsoft Windows, TortoiseSVN is a good choice. Under Linux, you can either use the svn command line tools or use a graphical user interface such as eSVN.
Once you have installed a svn client, you need to type the following command :
svn {co} {http://svn.cherrypy.org}
This will download the complete source code to your computer.
If you have downloaded the source code from the CherryPy subversion repository, then you should have a directory called svn.cherrypy.org. Then type the following commands:
cd {svn.cherrypy.org/trunk}
Then issue the following command (as root if you are under Unix/Linux):
python {setup.py} {install}
Alternately, since CherryPy has no dependencies, you don't have to run setup.py. Simply checkout the code into a directory which is on your Python path, such as your site-packages directory.
If you have installed CherryPy from the source code downloaded from the subversion repository, you can run the test suite to check if everything is fine on your system. Type the following commands:
cd {svn.cherrypy.org/trunk/cherrypy/test}
python {test.py}
If all tests pass, then they will be flagged as ok. If an error occurs,
please visit the main CherryPy website to report the issue.
Table of Contents
The best way to learn CherryPy is to look at example programs.
Save the code under a file named helloworld.py. Then to start up the application, type the following command:
python {helloworld.py}
You will see some information on your terminal window which are the log of the web server.
Then simply point your browser to http://localhost:8080 and say Bravo!
Example 2.1. Hello World
"""
Tutorial - Hello World
The most basic (working) CherryPy application possible.
"""
# Import CherryPy global namespace
import cherrypy
class HelloWorld:
""" Sample request handler class. """
def index(self):
# CherryPy will call this method for the root URI ("/") and send
# its return value to the client. Because this is tutorial
# lesson number 01, we'll just send something really simple.
# How about...
return "Hello world!"
# Expose the index method through the web. CherryPy will never
# publish methods that don't have the exposed attribute set to True.
index.exposed = True
# CherryPy always starts with cherrypy.root when trying to map request URIs
# to objects, so we need to mount a request handler object here. A request
# to '/' will be mapped to cherrypy.root.index().
cherrypy.root = HelloWorld()
if __name__ == '__main__':
# Use the configuration file tutorial.conf.
cherrypy.config.update(file = 'tutorial.conf')
# Start the CherryPy server.
cherrypy.server.start()
For security reasons, CherryPy requires developers to explicitly specify which methods may be accessed via the web. The method's 'exposed' attribute, when True, indicates that a given method is published to the web.
Example 2.2. Exposed Methods
"""
Tutorial - Multiple methods
This tutorial shows you how to link to other methods of your request
handler.
"""
import cherrypy
class HelloWorld:
def index(self):
# Let's link to another method here.
return 'We have an <a href="showMessage">important message</a> for you!'
index.exposed = True
def showMessage(self):
# Here's the important message!
return "Hello world!"
showMessage.exposed = True
cherrypy.root = HelloWorld()
if __name__ == '__main__':
cherrypy.config.update(file = 'tutorial.conf')
cherrypy.server.start()
The blogging system will feature some basic functionalities such as :
Our first step will be to define the directory structure of the projet. This structure is only one amongst others of course.
Example 2.3. Directory structure of the blog project
Imagine our root directory is called blog, then the structure will be :
blog/blog.py
blog/LICENSE
blog/README
blog/media/
blog/media/conf/
blog/media/css/
blog/media/db/
blog/media/feed/
blog/media/templates/
blog/media/utils/
blog/src/
Again this structure is not required by CherryPy itself. It is a choice made for this tutorial.
Mainly one can look at four the following directions when deciding to store and persist content :
By far the first choice is the most used at any rate. It is efficient, reliable, well-known and powerful. XML and native object database are gaining some success slowly but are still quite young.
The solution we have chosen is non of the above for keeping this tutorial simple. We do want to avoid having to import too many external modules. Besides since this blogging system is so simple, we can use another way to store and persist our content : pickling pure python objects thanks to the standard shelvemodule.
A ``shelf'' is a persistent, dictionary-like object. The difference with ``dbm'' databases is that the values (not the keys!) in a shelf can be essentially arbitrary Python objects -- anything that the pickle module can handle. This includes most class instances, recursive data types, and objects containing lots of shared sub-objects. The keys are ordinary strings.
This solution allows us to focus on CherryPy and not too much on the backend itself.
A templating language is meant to offer the developer and easy way to transform an input into an output of his/her choice. In the web application field, usually it refers to the presentation system to transform the content into nice XHTML output sent to the browser.
The CherryPy developers have made the clear choice of not providing any default templating system. The main reason is that CherryPy must to stay at low level and developers should not have the feeling like they must use a particular templating system. CherryPy allows actually the developer to choose his/her favourite templating system and work with it.
We could have written this blogging system by generating the HTML directly from the source code. Although this is totally possible we have felt it would be much cleaner to use a dedicated templating language. Our choise was CherryTemplate written and maintained by Remi Delon. It is a small package to install and which provides the basic functionnalities we will need : loop, condition, etc. Its learning curve is really low.
The first file we need to create is the blog.py file which will be
the entry point of the blog.
First we need to import the modules we will be using from this entry point.
Example 2.4. Blogging system - import modules
import sys
import time
sys.path.append('src')
import cherrypy
from cherrytemplate import cherrytemplate, renderTemplate
from entryManager import BlogEntryManager
from commentManager import BlogCommentManager
from comment import BlogComment
from admin import BlogAdmin
from cal import getCurrentCalendar
Example 2.5. Blogging system - the root class
class Blog: def __init__(self):
self.em = BlogEntryManager() self.cm = BlogCommentManager() cherrytemplate.defaultOutputEncoding = 'latin-1' cherrytemplate.defaultInputEncoding = 'latin-1' cherrytemplate.defaultTemplateDir = 'media/templates/'
CherryPy does not force you to define any kind of methods but index and
default are the ones CherryPy will look for by default. The
index() method is the equivalent to the index.html page used by default by
Apache. The default() method is called by CherryPy when all other lookup
fail. If CherryPy doesn't find any matching callable object, it will issue an
exception. index() is by far the most common one to be defined.
Before a method can be used to serve content it needs to be published and exposed. Publishing is the process of attaching an instance of a given callable to the main cherrypy object tree as we will see later. Exposing is done by setting the exposed attribute to the method that we want to be able to call from the client side.
Now we can define both methods as follow.
Example 2.6.
def index(self): entries = self.em.fetchLastEntries() cal = getCurrentCalendar() rssPath = cherrypy.request.base + '/media/feed/rss.xml' return renderTemplate(file = "Blog_show_entry.tmpl") index.exposed = True
def default(self, *args): cal = getCurrentCalendar() rssPath = cherrypy.request.base + '/media/feed/rss.xml' if len(args) == 3: date = "%s-%s-%s" % (args[0], args[1], args[2]) entries = self.em.fetchEntriesByDate(date) elif len(args) == 4: entry = self.em.fetchEntry(args[0], args[1], args[2], args[3]) if not entry: return renderTemplate(file = "error404.tmpl") entries = [entry] else: return self.index() return renderTemplate(file = "Blog_show_entry.tmpl") default.exposed = True
We will define two more exposed methods to our Blog class.
Example 2.7.
def comment(self, id): entryId = id entry = self.em.fetchEntryById(id) comments = self.cm.fetchCommentsByEntry(id) cal = getCurrentCalendar() rssPath = cherrypy.request.base + '/media/feed/rss.xml' return renderTemplate(file = "Blog_comment_add.tmpl") comment.exposed = True
def addComment(self, entryId, title, author, message): rssPath = cherrypy.request.base + '/media/feed/rss.xml' self.cm.addComment(BlogComment(title, author, message, entryId)) return self.comment(entryId) addComment.exposed = True
The core functionnailities will be held in some scripts that we are going to study in the following sections.
We will define a file called backendManager.py located under the
src directory. This file will define a class and its set of methods
to facilitate access and queries to our backend. Basically we will follow the CRUD
interface : Create, Retrieve, Update and Delete. Following is a snippet code from that
module:
Example 2.9.
import shelve
import threading
import time
_dbLocker = threading.Lock()
class BlogBackendManager:
def fetchAll(self):
data = []
try:
_dbLocker.acquire()
db = shelve.open('media/db/blob.db', 'r')
data = db.keys()
if db: db.close()
finally:
_dbLocker.release()
return data
Table of Contents
Abstract
CherryPy lets developers use Python to develop web applications, just as they would use Python for any other type of application. Building a web application with CherryPy is very straightforward and does not require the developer to change habits, or learn many features, before being able to produce a working application. This section will review the basic components which you will use to build a CherryPy application.Filters are one of the most important features of CherryPy. The CherryPy core can call user-defined functions at specific points during request processing; a filter is a class which defines those functions. Filters are designed to be called at a low level—the HTTP request/response level—and therefore should only be used in that context.
CherryPy comes with a set of built-in filters, but they're turned off by default. To enable them, you must use the configuration system as follows:
filterName.on = TrueExample 3.1. Turning on a default filter
[/entries/view]
tidyFilter.on = True
tidyFilter.tmpDir = "/tmp"
tidyFilter.strictXml = True
On the first line we define that the tidy filter will be used by the
core whenever the path /entries/view (or one of its sub-paths)
is called. On the two last lines we also define some parameters used by the
filter.
CherryPy lets you write your own filters as we will see in the
developer reference chapter. However, the way to use them is different from
the default filters. You do not declare custom filters within the
configuration file; instead, use the _cpFilterList attribute in
your source code:
Example 3.2. Using a non default filter
import cherrypy
from myfiltermodule import MyFilterClass
class Entry:
_cpFilterList = [ MyFilterClass() ]
def view(self, id):
# do suff...
view.exposed = True
class Root: pass
cherrypy.root = Root()
cherrypy.root.entries = Entry()
cherrypy.server.start()
As all objects below cherrypy.root.entries will inherit
the filter, there is no need to re-specify it in each
_cpFilterList underneath.
Keep in mind that the user-defined filters are called in the order you add them to the list.
The CherryPy configuration system provides fine-grained control over how each part of the application should react. You will use it for two reasons:
You will be able to declare the configuration settings either from a file or from a Python dictionary.
First of all, let's see how a typical configuration file is defined.
Example 3.3. Configuration file
# The configuration file called myconfigfile.conf
[global]
server.socketPort=8080
server.socketHost=""
server.socketFile=""
server.socketQueueSize=5
server.protocolVersion="HTTP/1.0"
server.logToScreen=True
server.logFile=""
server.reverseDNS=False
server.threadPool=10
server.environment="development"
[/service/xmlrpc]
xmlRpcFilter.on = True
[/admin]
sessionAuthenticateFilter.on=True
[/css/default.css]
staticFilter.on = True
staticFilter.file = "data/css/default.css"
# From your script...
cherrypy.config.update(file="myconfigfile.conf")
The settings can also be defined using a python dictionary instead of a file as follows:
Example 3.4. Configuration dictionary
settings = {
'global': {
'server.socketPort' : 8080,
'server.socketHost': "",
'server.socketFile': "",
'server.socketQueueSize': 5,
'server.protocolVersion': "HTTP/1.0",
'server.logToScreen': True,
'server.logFile': "",
'server.reverseDNS': False,
'server.threadPool': 10,
'server.environment': "development"
},
'/service/xmlrpc' : {
'xmlRpcFilter.on': True
},
'/admin': {
'sessionAuthenticateFilter.on' :True
},
'/css/default.css': {
'staticFilter.on': True,
'staticFilter.file': "data/css/default.css"
}
}
cherrypy.config.update(settings)
Each section of the configuration refers to a URL path; each path is
mapped to a published object of the tree handled by CherryPy. Therefore when
the server receives a request for /css/default.css, the static
filter will be called and the server will actually return the physical file
name data/css/default.css.
Since the path /service/xmlrpc has the XML-RPC filter
enabled, all the exposed methods of the object
cherrypy.root.service.xmlrpc will be treated as XML-RPC
methods.
The root entry, defined as global, is also responsible
for defining the server settings such as the port, the protocol version to
use by default, the number of threads to start with the server, etc.
All values in the configuration file must be valid Python values. Strings must be quoted, booleans must be True or False, etc.
The server.environment entry controls how CherryPy should
run. Three values are legal:
tracebacks are logged, but are not displayed in the browser
Abstract
CherryPy 2.1 includes a powerful sessions system provided via a new
sessionFilter.
First you need to enable the session filter through the
configuration system, by setting sessionFilter.on to
True. This gives you a variable called
cherrypy.session, which is a dictionary-like object
where you can read/store your session data. This dictionary always has a
special key called _id which contains the session
id.
Here is sample code showing how to implement a simple counter using sessions:
The following configuration options are available for "sessionFilter":
sessionFilter.on: True or
False (default): enable/disable sessions
sessionFilter.storageType: Specify which
storage type should be used for storing session data on the server.
Built-in types are Ram (default),
File and PostgreSQL (see Section 1.3.3, “Choosing the backend” for more info).
sessionFilter.storagePath: Specifies the directory
in which CherryPy puts the session files when sessionFilter.storageType is set
to File.
sessionFilter.timeout: The number of minutes of
inactivity before an individual session can be removed. It can be a
float (ex: 0.5 for 30 seconds). Defaults to 60.
sessionFilter.cleanUpDelay: Once in a while the
server cleans up old/expired sessions. This config option specifies
how often this clean up process should happen. The delay is in
minutes. Defaults to 5.
sessionFilter.cookieName: The name of the
cookie that CherryPy will use to store the session ID. Defaults to
sessionID.
sessionFilter.getDB: See the
PostgreSQL backend from Section 1.3.3, “Choosing the backend”.
sessionFilter.deadlockTimeout: See Section 1.3.5, “Handling concurrent requests for the same session data”.
sessionFilter.onCreateSession: See Section 1.3.6, “Being notified when sessions are created/deleted”.
sessionFilter.onDeleteSession: See Section 1.3.6, “Being notified when sessions are created/deleted”.
sessionFilter.storageClass: See Section 1.3.4, “Writing your own custom backend”.
CherryPy comes with multiple build-in backends for storing session data on the server side. They are:
Ram: All data is stored in RAM; this is the
fastest storage, but it means that the data will be lost if you
restart the server; and it also means that it won't scale to multiple
processes/machines
File: All data is stored on disk; this is a bit
slower than Ram storage, but the data will persist if you restart the
server. It also means that data can be shared amongst multiple
CherryPy processes, either on the same machine, or on multiple
machines if all machines have access to the same disk (for example,
via NFS).
PostgreSQL: This backend is included
with CherryPy to show how easy it is to implement your own custom
backend for the session system. All data is stored in a PostgreSQL
database; storing your data in a database is the recommend setup for
production if you have a very high traffic website and you need to scale
your site across multiple machines. To use this backend, you'll need to
create the following table in your PostgreSQL database:
create table session (
id varchar(40),
data text,
expiration_time timestamp
)
You also need to programmatically set the
sessionFilter.getDB config option to a function that
returns a DB connection.Ram backend, the session data is saved as soon as you stick it in cherrypy.session. So even if an error occurs later on in the page handler the data is still saved; this is not the case for the other backends.
By default, CherryPy comes with 3 built-in backends, but if you have specific needs, it is very easy to implement your own custom backend (for instance, another database, or an XML-RPC server, ...). To do so, all you have to do is write a class that implements the following methods:
class MyCustomBackend:
def save(self, id, data, expirationTime):
""" Save the session data and expirationTime for that session id """
def load(self, id):
""" Load the session data and expirationTime for 'id' and return
a tuple (data, expirationTime) (even if the session is
expired). Return None if id doesn't exist. """
def cleanUp(self):
""" Delete expired session data from storage and call
'onDeleteSession' for each deleted session id """
Note that if you want to use explicit
locking (see Section 1.3.5, “Handling concurrent requests for the same session data”), you also have to implement
two extra methods: acquireLock and
releaseLock.
Once you have written this class, you have to programmatically set
the sessionFilter.storageClass config option to this
class.
If you need help in writing your own custom backend it is a good
idea to look at how the current ones (ram, file and postgresql) are
implemented. They are implemented in the file
cherrypy/lib/filter/sessionfilter.py
It is normally quite rare to have two simultaneous requests with the same session ID. It means that a same browser is making 2 requests to your server at the same time (to dynamic pages ... static data like images don't have sessions). However, this case can happen (if you're using frames for instance), and it will happen more and more often as more and more people start using Ajax.
In that case, we need to make sure that access to the session data is serialized. This way, threads can't both modify the data at the same time and leave it in an inconsistent state.
You can easily make CherryPy serialize access to the session data by setting the sessionFilter.locking config option to implicit (the default is explicit, which means that CherryPy won't do any locking for you). In the implicit mode,
if a browser makes a second request while a first request is still being
handled by the server, the second request will block while the first
request is accessing the data. As soon as the first request is finished
then the second request will be able to access it.
This means that the second request will block until the first request is finished.
It is possible to configure the sessionFilter so
that it calls some special callback functions from your code when sessions
are being created/deleted. To do so you have to set the
sessionFilter.onCreateSession and
sessionFilter.onDeleteSession config options. When a
session is created/deleted, CherryPy will call these functions and pass
them the session data.
CherryPy is a low-level framework for building web applications, and thus does not offer high-level features such as an integrated templating system. This is quite a different point of view from many other web frameworks. CherryPy does not force you to use a specific templating language; instead, it allows you to plug in your favourite one as you see fit.
CherryPy works with all the main templating systems:
You will find recipes on how to use them on the CherryPy website.
Static content is now handled by a filter called "staticFilter" that
can easily be enabled and configured in your config file. For instance, if
you wanted to serve /style.css from
/home/site/style.css and /static/* from
/home/site/static/*, you can use the following
configuration:
Example 3.6. Static filter configuration
[global]
staticFilter.root = "/home/site"
[/style.css]
staticFilter.on = True
staticFilter.file = "style.css"
[/static]
staticFilter.on = True
staticFilter.dir = "static"
The staticFilter.root entry can be either absolute or
relative. If absolute, static content is sought within that absolute path.
Since CherryPy cannot guess where your application root is located, relative
paths are assumed to be relative to the directory where your
cherrypy.root class is defined (if you do not provide a root,
it defaults to "", and therefore to the directory of your
cherrypy.root class).
As an application developer, the design of your application affects whether you choose to use absolute or relative paths. If you are creating a one-off application that will only be deployed once, you might as well use absolute paths. But you can make multiple deployments easier by using relative paths, letting CherryPy calculate the absolute path each time for you. Absolute paths, however, give deployers the ability to place static content on read-only filesystems, or on faster disks.
Before version 2.1, CherryPy handled file uploads by reading the entire file into memory, storing it in a string, and passing it to the page handler method. This worked well for small files, but not so well for large files.
CherryPy 2.1 uses the python cgi module to parse the
POST data. When a file is being uploaded, the cgi module
stores it in a temp file and returns a FieldStorage instance
which contains information about this file. CherryPy then passes this
FieldStorage instance to the method. The
FieldStorage instance has the following attributes:
file: the file(-like) object from which you can
read the datafilename: the client-side filenametype: the content-type of the file[global] server.socketPort: port number where the server is listening (defaults to 8080)
[global] server.logFile: path to a file to log CherryPy server activity. Items logged include startup config info, tracebacks and HTTP requests. It is disabled by default and everything is logged to the screen.
[global] server.logAccessFile: path to a file where access log data will be stored in Common Log Format. The default is to write access log data to the screen. If a file is specified, the access log data is no longer written to the screen.
[global] server.logToScreen: controls whether any log data is written to the screen. It defaults to on (True). For performance reasons, it is best to have this option turned off on a production server.
[global] server.logTracebacks: controls whether or not tracebacks are written to the log (screen or otherwise). Defaults to on (True) If set to False, only a 500 return code will be logged in the access log.
[global] server.maxRequestHeaderSize: maximum acceptable size of a request header, in bytes (defaults to 500KB). If a longer request arrives, the server will interrupt it and return a 413 error. This setting is global (ie: doesn't depend on the path). Set it to zero to remove the limit
[/path] server.maxRequestBodySize: maximum acceptable size of a request body, in bytes (defaults to 100MB). If a longer request body arrives, the server will interrupt it and return a 413 error. This setting can be configured per path. This is useful to limit the size of uploaded files. Set it to zero to remove the limit
TODO: other config options
At its most basic, CherryPy is designed to allow the production of simple websites without having to think about any of the details of HTTP. Notice we're saying HTTP (the transport), not HTML (the markup language)! In particular, developers should not have to concern themselves with:
Responding to unpublished requests
Logging and notifying users appropriately when unhandled exceptions occur
The difference between query strings and POSTed params
The decoding and unpacking of request headers and bodies, including file uploads
Response status or headers
For the most part, simple "page handlers" (functions attached to
cherrypy.root), should never have to refer to cherrypy at all! They receive
params via function arguments, and return content directly. Advanced functionality is
most often enabled via the built-in filters, which encapsulate the particulars of HTTP,
and can be completely controlled via the config file.
Simple apps are produced simply, but when a developer needs to step out of the
mundane and provide real value, they should be able to leverage the complete power and
flexibility of the HTTP specification. In general, the HTTP request and response messages
are completely represented in the cherrypy.request and
.response objects. At the lowest level, a developer should be able to
generate any valid HTTP response message by modifying
cherrypy.response.status, .headerMap, and/or
.body.
The design of HTTP itself is guided by REST, a set of principles which constrain its expressivity and therefore its implementation. HTTP is a transfer protocol which enables the exchange of representations of resources. In a RESTful design, clients never expect to access a resource directly; instead, they request a representation of that resource. For example, if a resource has both an XML and an HTML representation, then an HTTP/1.1 server might be expected to inspect the Accept request header in order to decide which representation to serve in response.
It's important to clarify some terminology, here. In REST terms, a "resource" is "any concept that might be the target of an author’s hypertext reference...a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time". A resource is not the request, nor the response, in an HTTP conversation. "The resource is not the storage object. The resource is not a mechanism that the server uses to handle the storage object. The resource is a conceptual mapping — the server receives the identifier (which identifies the mapping) and applies it to its current mapping implementation (usually a combination of collection-specific deep tree traversal and/or hash tables) to find the currently responsible handler implementation and the handler implementation then selects the appropriate action+response based on the request content."
CherryPy, therefore, does not provide REST resources, nor model them, nor serve them. Instead, it provides mappings between identifiers (URI's) and handlers (functions). It allows application developers to model resources, perhaps, but it only serves representations of resources.
By default, these identifier-to-handler mappings (which we will call "handler dispatch" from now on) follow a simple pattern: since the path portion of a URI is hierarchical, CherryPy arranges handlers in a similar heirarchy, starting at cherrypy.root, and branching on each attribute; every leaf node in this tree must be "exposed" (but the branches need not be, see section 2.2). Note in particular that, although the query portion of a Request-URI is part of the resource identifier, CherryPy does not use it to map identifiers to handlers. Application developers may use the query string to further identify the requested resource, of course, but CherryPy, not having any domain-specific knowledge about the format or semantic of a query string, doesn't try to guess.
Filters, then, are CherryPy's way to wrap or circumvent the default handler dispatch. EncodingFilter, for example, wraps the response from a handler, encoding the response body as it is produced. StaticFilter, on the other hand, intercepts some requests (based on the path portion of the Request-URI) and implements its own identifier-to-handler mapping. Developers who wish to provide their own handler dispatch mechanisms are encouraged to do so via a filter.
This attribute is a string containing the IP address of the client. It will be an empty string if it is not available.
This attribute is an int containing the TCP port number of the client. It will be -1 if it is not available.
This attribute is a string containing the remote hostname of the client.
This attribute is a dictionary containing the received HTTP headers, with automatically titled keys (e.g., "Content-Type"). As it's a dictionary, no duplicates are allowed.
This attribute is a list of (header, value) tuples containing the received HTTP headers. In general, you probably want to use headerMap instead; this is only here in case you need to inspect duplicates in the request headers.
This attribute is a string containing the first line of the raw HTTP request; for example, "GET /path/page HTTP/1.1".
This attribute is a SimpleCookie instance from the standard library's Cookie module which contains the incoming cookie values from the client.
This attribute is the input stream to the client, if applicable. See cherrypy.request.processRequestBody for more information.
This attribute is the request entity body, if applicable. See cherrypy.request.processRequestBody for more information.
This attribute specifies whether or not the request's body (request.rfile, which is POST or PUT data) will be handled by CherryPy. If True (the default for POST and PUT requests), then request.rfile will be consumed by CherryPy (and unreadable after that). If the request Content-Type is "application/x-www-form-urlencoded", then the rfile will be parsed and placed into request.paramMap; otherwise, it will be available in request.body. If cherrypy.request.processRequestBody is False, then the rfile is not consumed, but will be readable by the exposed method.
This attribute is a string containing the HTTP request method, such as GET or POST.
This attribute is a string containing the HTTP protocol of the request in the form of HTTP/x.x
This attribute is a Version object which represents the HTTP protocol. It's the
same os request.protocol, but allows easy comparisons like if
cherrypy.request.version >= "1.1": do_http_1_1_thing.
This attribute is a string containing the query string of the request (the part of the URL following '?').
This attribute is a string containing the path of the resource the client requested.
This attribute is a dictionary containing the query string and POST arguments of this request.
This attribute is a string containing the root URL of the server. By default, it is equal to request.scheme://request.headerMap['Host'].
This attribute is a string containing the URL the client requested. By default, it
is equal to request.base + request.path.
This attribute is a string containing the path of the exposed method that will be called to handle this request. This is usually the same as cherrypy.request.path, but can be changed in a filter to change which method is actually called.
This attribute is a string containing the original value of cherrypy.request.path, in case it is modified by a filter during the request.
This attribute is a string containing the original value of cherrypy.request.paramMap, in case it is modified by a filter during the request.
This attribute is a dictionary with automatically titled keys (e.g., "Content-Length"). It holds all outgoing HTTP headers to the client.
This attribute is a list of (header, value) tuples. It's not available until the response has been finalized; it's really only there in the extremely rare cases when you need duplicate response headers. In general, you should use request.headerMap instead.
This attribute is a SimpleCookie instance from the standard library's Cookie module. It contains the outgoing cookie values.
This attribute is originally just the return value of the exposed method, but by the end of the request it must be an iterable (usually a list or generator of strings) which will be the content of the HTTP response.
This attribute is a string containing the HTTP response code in the form "### Reason-Phrase", i.e. "200 OK". You may also set it to an int, in which case the response finalization process will supply a Reason-Phrase for you.
This attribute is a Version object, representing the HTTP protocol version of the response. This is not necessarily the value that will be written in the response! Instead, it should be used to determine which features are available for the response. For example, an HTTP server may send an HTTP/1.1 response even though the client is known to only understand HTTP/1.0—the response.version will be set to Version("1.0") to inform you of this, so that you (and CherryPy) can restrict the response to HTTP/1.0 features only.
Start the CherryPy Server. Simple websites may call this without any arguments, to run the default server. If initOnly is False (the default), this function will block until KeyboardInterrupt or SystemExit is raised, so that the process will persist. When using one of the built-in HTTP servers, you should leave this set to False. You should only set it to True if you're running CherryPy as an extension to another HTTP server (for example, when using Apache and mod_python with CherryPy), in which case the foreign HTTP server should do its own process-management.
Use the serverClass argument to specify that you wish to use an HTTP server other than the default, built-in WSGIServer. If missing, config.get("server.class") will be checked for an alternate value; otherwise, the default is used. Possible alternate values (you may pass the class names as a string if you wish):
cherrypy._cphttpserver.CherryHTTPServer: this will load the
old, single-threaded built-in HTTP server. This server is deprecated and will
probably be removed in CherryPy 2.2.
cherrypy._cphttpserver.PooledThreadServer: this will load the
old, multi-threaded built-in HTTP server. This server is deprecated and will
probably be removed in CherryPy 2.2.
cherrypy._cphttpserver.embedded_server: use this to
automatically select between the CherryHTTPServer and the PooledThreadServer
based on the value of config.get("server.threadPool") and
config.get("server.socketFile").
None: this will not load any HTTP server. Note that this is
not the default; the default (if serverClass is not given) is to load the
WSGIServer.
Any other class (or dotted-name string): load a custom HTTP server.
You must call this function from Python's main thread, and set initOnly to False, if you want CherryPy to shut down when KeyboardInterrupt or SystemExit are raised (including Ctrl-C). The only time you might want to do otherwise is if you run CherryPy as a Windows service, or as an extension to, say, mod_python, and even then, you might want to anyway.
If the "initOnly" argument to server.start is True, this will be False, and vice-versa.
Whatever HTTP server class is set in server.start will be stuck in here.
Whatever HTTP server class is set in server.start will be instantiated and stuck in here.
One of three values, indicating the state of the server:
STOPPED = 0: The server hasn't been started, and will not accept requests.
STARTING = None: The server is in the process of starting, or an error occured while trying to start the server.
STARTED = 1: The server has started (including an HTTP server if requested), and is ready to receive requests.
True if the server is ready to receive requests, false otherwise. Read-only.
Since server.start usually blocks, other threads need to be started before calling server.start; however, they often must wait for server.start to complete it's setup of the HTTP server. Use this function from other threads to make them wait for the HTTP server to be ready to receive requests.
Since server.start usually blocks, use this to easily run another function in a new thread. It starts the new thread and then runs server.start. The new thread automatically waits for the server to finish its startup procedure.
Stop the CherryPy Server. Well, "suspend" might be a better term—this doesn't terminate the process.
Usually None, set this to KeyboardInterrupt() or SystemExit() to shut down the entire process. That is, the new exception will be raised in the main thread.
A list of functions that will be called when the server starts.
A list of functions that will be called when the server stops.
A list of functions that will be called when each request thread is started. Note that such threads do not need to be started or controlled by CherryPy; for example, when using CherryPy with mod_python, Apache will start and stop the request threads. Nevertheless, CherryPy will run the onStartThreadList functions upon the first request using each distinct thread.
A list of functions that will be called when each request thread is stopped.
This function returns the configuration value for the given key. The function checks if the setting is defined for the current request path; it walks up the request path until the key is found, or it returns the default value. If returnSection is True, the function returns the configuration path where the key is defined instead.
The getAll function returns a list containing a (path, value) tuple for all occurences of the key within the request path. This function allows applications to inherit configuration data defined for parent paths.
This exception can be used to automatically send a response using a http status code, with an appropriate error page.
Utility class that exposes a getitem-aware object. It does not provide index() or default() methods, and it does not expose the individual item objects - just the list or dict that contains them. User-specific index() and default() methods can be implemented by inheriting from this class.
Utility class that restores positional parameters functionality that was found in 2.0.0-beta.
Returns a list of (start, stop) indices from a Range request header. Returns None if no such header is provided in the request. Each (start, stop) tuple will be composed of two ints, which are suitable for use in a slicing operation. That is, the header "Range: bytes=3-6", if applied against a Python string, is requesting resource[3:7]. This function will return the list [(3, 7)].
Set status, headers, and body in order to serve the file at the given path. The Content-Type header will be set to the contentType arg, if provided. If not provided, the Content-Type will be guessed by the extension of the file. If disposition is not None, the Content-Disposition header will be set to "<disposition>; filename=<name>". If name is None, it will be set to the basename of path. If disposition is None, no Content-Disposition header will be written.
This module both provides code-coverage tools, and may also be run as a script. To use this module, or the coverage tools in the test suite, you need to download 'coverage.py', either Gareth Rees' original implementation or Ned Batchelder's enhanced version.
Set cherrypy.codecoverage to True to turn on coverage tracing. Then, use the covercp.serve() function to browse the results in a web browser. If you run this module as a script (i.e., from the command line), it will call serve() for you.
You can profile any of your page handlers (exposed methods) as follows:
Example 3.7. Profiling example
from cherrypy.lib import profile
class Root:
p = profile.Profiler("/path/to/profile/dir")
def index(self):
self.p.run(self._index)
index.exposed = True
def _index(self):
return "Hello, world!"
cherrypy.root = Root()Set the config entry: "profiling.on = True" if you'd rather turn on profiling for all requests. Then, use the serve() function to browse the results in a web browser. If you run this module as a script (i.e., from the command line), it will call serve() for you.
Developers: this module should be used whenever you make significant changes to CherryPy, to get a quick sanity-check on the performance of the request process. Basic requests should complete in about 5 milliseconds on a reasonably-fast machine running Python 2.4 (Python 2.3 will be much slower due to threadlocal being implemented in Python, not C). You can profile the test suite by supplying the --profile option to test.py.
This module provides a brute-force method of reloading application files on the fly. When the config entry "autoreload.on" is True (or when "server.environment" is "development"), CherryPy uses the autoreload module to restart the current process whenever one of the files in use is changed. The mechanism by which it does so is pretty complicated:
_cpOnError is a function for handling unanticipated exceptions, whether raised by CherryPy itself, or in user applications. The default simply raises HTTPError(500).
Filters provide a powerful mechanism for extending CherryPy. The aim is to provide code called at the HTTP request level itself. More specifically it means that you can write code that will be called:
The baseurlfilter changes the base url of a request. It is useful for running CherryPy behind Apache with mod_rewrite.
The baseurlfilter has the following configuration options
The decoding filter can be configured to automatically decode incoming requests.
The decodingfilter has the following configuration options:
The encodingfilter can be configured to automatically encode outgoing responses.
The encodingfilter has the following configuration options:
The gzipfilter will automatically gzip outgoing requests, if it is supported by the client.
The gzipfilter does not have any configuration options.
The logdebuinfofilter adds debug information to each page. The filter is automatically turned on when "server.environment" is set to "development".
The logdebuginfofilter has the following configuration options:
The static filter allows CherryPy to serve static files.
The staticfilter has the following configuration options:
staticFilter.root
The tidyfilter cleans up returned html by running the response through Tidy.
Note that we use the standalone Tidy tool rather than the python mxTidy module. This is because this module doesn't seem to be stable and it crashes on some HTML pages (which means that the server would also crash.)
The tidyfilter has the following configuration options:
The virtualhostfilter changes the ObjectPath based on the Host. Use this filter when running multiple sites within one CP server.
The virtualhostfilter has the following configuration options:
The xmlrpcfilter converts XMLRPC to the CherryPy2 object system and vice-versa.
PLEASE NOTE: beforeRequestBody: Unmarshalls the posted data to a methodname and parameters. - These are stored in cherrypy.request.rpcMethod and .rpcParams - The method is also stored in cherrypy.request.path, so CP2 will find the right method to call for you, based on the root's position. beforeFinalize: Marshalls cherrypy.response.body to xmlrpc. - Until resolved: cherrypy.response.body must be a python source string; this string is 'eval'ed to return the results. This will be resolved in the future. - Content-Type and Content-Length are set according to the new (marshalled) data
The xmlrpcfilter does not have any configuration options.
CherryPy 2.1 supports arbitrary WSGI servers, and includes its own WSGI server (the default). This means that you should be able to deploy your CherryPy application using Apache or IIS (among others) without any changes to your application--only the deployment scripts will change.
Copyright (c) 2004, CherryPy Team (team@cherrypy.org) All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.