The CherryPy Documentation

Revision: 2.1.0


Table of Contents

Preface
1. About this Manual
2. Introduction
1. Getting started
1. Installing CherryPy from a release package
1.1. Obtaining a release package
1.2. Installing from a release package
2. Installing CherryPy from the Subversion repository
2.1. Obtaining the package from the Subversion repository
2.2. Installing the package from the Subversion repository
3. Running the test programs
2. CherryPy By Example
1. Hello World
2. Exposed Methods
3. A real case application : A blog.
3.1. Features of the blog
3.2. Setting up the project
3.3. Design consideration
3.4. Tools
3.5. Building the application
3.6. Running the application
3. Reference
1. Application developer reference
1.1. Filters
1.2. Configuration system overview
1.3. Session Management
1.4. Templating language independent
1.5. Static content handling
1.6. File upload
1.7. Exceptions and Error Handling
2. Administrator reference
2.1. Install a CherryPy application
2.2. Config options reference
2.3. Configure an application
2.4. Production Setup
3. CherryPy framework developer reference
3.1. Detailed overview of CherryPy
3.2. Design choices
3.3. API reference
3.4. Filters explained
3.5. Web servers architecure (HTTP servers which CP supplies)
A. Appendix
1. History of CherryPy
1.1. CherryPy 1
1.2. CherryPy 2
2. Coding style
3. License

List of Figures

3.1. The HTTP conversation
3.2. The autoreload process

List of Examples

2.1. Hello World
2.2. Exposed Methods
2.3. Directory structure of the blog project
2.4. Blogging system - import modules
2.5. Blogging system - the root class
2.6.
2.7.
2.8.
2.9.
3.1. Turning on a default filter
3.2. Using a non default filter
3.3. Configuration file
3.4. Configuration dictionary
3.5.
3.6. Static filter configuration
3.7. Profiling example

Preface

1. About this Manual

2. Introduction

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.

Chapter 1. Getting started

1. Installing CherryPy from a release package

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.

1.1. Obtaining a release package

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.

1.2. Installing from a release 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}

2. Installing CherryPy from the Subversion repository

2.1. Obtaining the package from the Subversion repository

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.

2.2. Installing the package from the Subversion repository

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.

3. Running the test programs

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.

Chapter 2. CherryPy By Example

The best way to learn CherryPy is to look at example programs.

1. Hello World

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()


        
      

2. Exposed Methods

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()


        
      

3. A real case application : A blog.

3.1. Features of the blog

Abstract

The following sections will describe the step to build a simple blogging system. It does not aim to create a comprehensive one but to give you an overview of how to build a CherryPy application.

The blogging system will feature some basic functionalities such as :

  • Add new entries
  • Delete existing entries
  • Add a new comment
  • Display a calendar
  • Use positional parameters
  • Present a RSS feed

3.2. Setting up the project

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 :

      1 blog/blog.py
      2 blog/LICENSE
      3 blog/README
      4 blog/media/
      5 blog/media/conf/
      6 blog/media/css/
      7 blog/media/db/
      8 blog/media/feed/
      9 blog/media/templates/
      10 blog/media/utils/
      11 blog/src/
      
1

This is the main script of our application. It contains the code to start up the web server and the application.

2

Your application should always contain a license.

3

Your application should also come with a readme file.

4

We will divide the directory structure into two main sub directories. One will deal with the source code itself, and the other one will deal with all the data you might work with.

5

Contains the configuration file we will define for the application.

6

Contains the CSS stylesheet we will be using.

7

Our blogging system will use a very simple interface to store content as you will see later. This directory will hold the data.

8

We will only support RSS here but as you may extend yourself the applictaion, this directory will let you hold all different kind of feed format files.

9

Contains all templating files we will be using.

10

Where to put some helper files we will need.

11

Contains the source code itself.

Again this structure is not required by CherryPy itself. It is a choice made for this tutorial.

3.3. Design consideration

3.4. Tools

Abstract

3.4.1. The backend: persistence

Mainly one can look at four the following directions when deciding to store and persist content :

  • Native SQL driven database
  • Native XML driven database
  • Native Objects driven database

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.

3.4.2. Templating : presentation

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.

3.5. Building the application

3.5.1. Main entry point

The first file we need to create is the blog.py file which will be the entry point of the blog.

3.5.1.1. Importing required modules

First we need to import the modules we will be using from this entry point.

Example 2.4. Blogging system - import modules

    1 import sys
    import time
            
    2  sys.path.append('src')
            
    3  import cherrypy
    4  from cherrytemplate import cherrytemplate, renderTemplate

    5
    from entryManager import BlogEntryManager
    from commentManager import BlogCommentManager
    from comment import BlogComment
    from admin import BlogAdmin
    from cal import getCurrentCalendar
          
1

We use the sys module to be able to add a directory to the search path where Python looks for modules.

2

Here we add the sub-directory src to the Python search path.

3

CherryPy requires only one import. In version 2.0 of CherryPy, it used to be from cherrypy import cpg but not any longer.

4

Import two modules from CherryTemplate. The first one is used to modify some global variable of CherryTemplate as we will see later on. The second one is the actual function to parse a template file and fetch the output.

5

The last modules imported are those we will write later on in this tutorial.

3.5.1.2. The main class

Example 2.5. Blogging system - the root class

1class Blog:
  def __init__(self):
    2
    self.em = BlogEntryManager()
    self.cm = BlogCommentManager()
    cherrytemplate.defaultOutputEncoding = 'latin-1'
    cherrytemplate.defaultInputEncoding = 'latin-1'
    cherrytemplate.defaultTemplateDir = 'media/templates/'
          
1

CherryPy needs at least one python callable at its root (eg: a class or a function). Here we will eb using a class called Blog.

2

Since a CherryPy application runs as a long process on your system, we can define variables that will be shared during the full run of the process. In this case we need a manager of entries and comments, classes tha we will define later on. Wel also define some global variable used by CherryTemplate.

3.5.1.3. Defining an index and a default method

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. 

 1
    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
           
 2
    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
          
1

When the index method is called we fetch the last entries added to the blog as well as the calendar of the current month (we will see later how to build it). Then we define the RSS feed path.

Those three variables will be transparently passed to the CherryTemplate which is rendered through the renderTemplate() function. Since we have defined the templates directory as a global variable of CherryTemplate, we simply need to provide the name of the template itself to the method.

We will then serve to the client the string resulting from the rendering, although CherryPy allows you to return a string, a list, a generator to serve the content

index.exposed = True tells CherryPy that this method is exposed and available to serve content.

2

The default method is called when CherryPy failed to map the requested URL to an exposed object in the published objects tree, but you can also use it to slightly change CherryPy's behavior.

In this particular context we will use default() allow URL with positional parameters such as : http://myhost/2005/06/18/78, which would be the equivalent to : http://myhost/?year=2005&month=06&day=18&entry=78. The former URL looks nicer and is more search engine friendly.

This behavior is not automatically handled by CherryPy and using the default method is the most common workaround.

First we get the current month calendar then we set the RSS feed path. Then we check what to do next by testing the number of passed arguments to the request. If this equals to three then the user asked to view a full day and all its entries. If it equals to four he specified the entry id as well. Otherwise we simply fallback to callback index().

3.5.1.4. Serving more content

We will define two more exposed methods to our Blog class.

Example 2.7. 

 1
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
 
 2
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
          
1

Called when an user wants to read the comments added to an entry.

2

Called when an user submitted a new comment through the HTML form.

3.5.1.5. Setting up the tree and the server

Finally we need to set up the CherryPy tree of published objects, specify what settings we need and finally start the server.

Example 2.8. 

1
    cherrypy.root = Blog()
    cherrypy.root.admin = BlogAdmin()

2
    cherrypy.config.update(file='media/conf/Blog.conf')
3
    cherrypy.server.start()
          
1

Define the tree structure. Our blogging system only publish two objects.

2

Our settings will be defined in a seperate file. We could have defined them inline as a Python dictionnary.

3

Let's start the server.

3.5.2. Building the core

The core functionnailities will be held in some scripts that we are going to study in the following sections.

3.5.2.1. The backend

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
          1
          _dbLocker = threading.Lock()
          
          class BlogBackendManager:
              2
              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
        
1 We will hold a global lock to ensure the database access will be protected. This is needed since CherryPy is a multithreaded application, each thread handling one user agent request. As you can notice this lock is global to the entire application, therefore no more than one thread will be able to access the database at one given time. This is a very simplistic principle and not a usable one on a larger application, but as we already said, our purpose is to show how to build an application without too much complexity.
2 This method will simply connect to the database and fetch all entries. We make sure the lock is always released by calliong the release method within the finallystatement, thus whatever happens after the lock has been acquired it will be released.

3.6. Running the application

Abstract

Chapter 3. Reference

1. Application developer reference

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.

1.1. Filters

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:

  • First you must decide where to enable the filter. CherryPy maintains a tree of published objects; you must decide which branch should use the filter. The filter will then apply to that branch and all its children in the tree. Remember that the tree is accessed as a path and then mapped internally by the core to match the correct exposed object.
  • Second in the config file you must turn the filter on like this : filterName.on = True

Example 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.

1.2. Configuration system overview

The CherryPy configuration system provides fine-grained control over how each part of the application should react. You will use it for two reasons:

  • Web server settings
  • Enabling filters per path

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:

  • development
    • logDebugInfoFilter is enabled by default
    • HTTPErrors (and therefore the default _cpOnError) display tracebacks in the browser if errors occur
    • autoreload is enabled by default
  • production
    • logDebugInfoFilter is disabled by default
    • tracebacks are logged, but are not displayed in the browser

    • autoreload is disabled by default
  • staging (same as production for the moment)

1.3. Session Management

Abstract

CherryPy 2.1 includes a powerful sessions system provided via a new sessionFilter.

1.3.1. Using Sessions

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:

Example 3.5. 

            import cherrypy
            class Root:
                def index(self):
                    count = cherrypy.session.get('count', 0) + 1
                    cherrypy.session['count'] = count
                    return 'Counter: %s' % count
                index.exposed = True

            cherrypy.config.update({'sessionFilter.on': True})
            cherrypy.root = Root()
            cherrypy.server.start()
            

1.3.2. Configuring sessions

The following configuration options are available for "sessionFilter":

1.3.3. Choosing the 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.
Note that when using the 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.

1.3.4. Writing your own custom backend

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

1.3.5. Handling concurrent requests for the same session data

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.

1.3.6. Being notified when sessions are created/deleted

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.

1.4. Templating language independent

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.

1.5. Static content handling

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.

1.6. File upload

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 data
  • filename: the client-side filename
  • type: the content-type of the file

1.7. Exceptions and Error Handling

Unhandled exceptions raised inside CherryPy applications result in a call to the _cpOnError function. HTTPError and HTTPRedirect exceptions do not result in calls to _cpOnError. HTTPError exceptions force the server to set response status and return an error page.

2. Administrator reference

2.1. Install a CherryPy application

2.2. Config options reference

2.2.1. List of core (ie: not for filters) config options:

  • [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

2.3. Configure an application

2.4. Production Setup

2.4.1. Quick overview

2.4.2. Servers

2.4.2.1. Built in server
2.4.2.2. Behind Apache
2.4.2.3. Built in server
2.4.2.4. FastCGI
2.4.2.5. mod_python

3. CherryPy framework developer reference

3.1. Detailed overview of CherryPy

3.1.1. The HTTP conversation (request/response process)

CherryPy is designed to be deployed in a variety of environments, and therefore has a number of layers involved in handling an HTTP request.

Figure 3.1. The HTTP conversation

The HTTP conversation

3.2. Design choices

3.2.1. A layered API

3.2.1.1. Simple apps should not require any knowledge of HTTP

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.

3.2.1.2. Advanced apps should have full control over (valid) HTTP output

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.

3.2.1.2.1. How CherryPy relates to REST (REpresentational State Transfer)

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.

3.3. API reference

3.3.1. cherrypy.threadData

This attribute holds attributes that map to this thread only.

3.3.2. cherrypy.request

3.3.2.1. cherrypy.request.remoteAddr

This attribute is a string containing the IP address of the client. It will be an empty string if it is not available.

3.3.2.2. cherrypy.request.remotePort

This attribute is an int containing the TCP port number of the client. It will be -1 if it is not available.

3.3.2.3. cherrypy.request.remoteHost

This attribute is a string containing the remote hostname of the client.

3.3.2.4. cherrypy.request.headerMap

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.

3.3.2.5. cherrypy.request.headers

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.

3.3.2.6. cherrypy.request.requestLine

This attribute is a string containing the first line of the raw HTTP request; for example, "GET /path/page HTTP/1.1".

3.3.2.7. cherrypy.request.simpleCookie

This attribute is a SimpleCookie instance from the standard library's Cookie module which contains the incoming cookie values from the client.

3.3.2.8. cherrypy.request.rfile

This attribute is the input stream to the client, if applicable. See cherrypy.request.processRequestBody for more information.

3.3.2.9. cherrypy.request.body

This attribute is the request entity body, if applicable. See cherrypy.request.processRequestBody for more information.

3.3.2.10. cherrypy.request.processRequestBody

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.

3.3.2.11. cherrypy.request.method

This attribute is a string containing the HTTP request method, such as GET or POST.

3.3.2.12. cherrypy.request.protocol

This attribute is a string containing the HTTP protocol of the request in the form of HTTP/x.x

3.3.2.13. cherrypy.request.version

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.

3.3.2.14. cherrypy.request.queryString

This attribute is a string containing the query string of the request (the part of the URL following '?').

3.3.2.15. cherrypy.request.path

This attribute is a string containing the path of the resource the client requested.

3.3.2.16. cherrypy.request.paramMap

This attribute is a dictionary containing the query string and POST arguments of this request.

3.3.2.17. cherrypy.request.base

This attribute is a string containing the root URL of the server. By default, it is equal to request.scheme://request.headerMap['Host'].

3.3.2.18. cherrypy.request.browserUrl

This attribute is a string containing the URL the client requested. By default, it is equal to request.base + request.path.

3.3.2.19. cherrypy.request.objectPath

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.

3.3.2.20. cherrypy.request.originalPath

This attribute is a string containing the original value of cherrypy.request.path, in case it is modified by a filter during the request.

3.3.2.21. cherrypy.request.originalParamMap

This attribute is a string containing the original value of cherrypy.request.paramMap, in case it is modified by a filter during the request.

3.3.2.22. cherrypy.request.scheme

This attribute is a string containing the URL scheme used in this request. It is either "http" or "https".

3.3.3. cherrypy.response

3.3.3.1. cherrypy.response.headerMap

This attribute is a dictionary with automatically titled keys (e.g., "Content-Length"). It holds all outgoing HTTP headers to the client.

3.3.3.2. cherrypy.response.headers

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.

3.3.3.3. cherrypy.response.simpleCookie

This attribute is a SimpleCookie instance from the standard library's Cookie module. It contains the outgoing cookie values.

3.3.3.4. cherrypy.response.body

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.

3.3.3.5. cherrypy.response.status

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.

3.3.3.6. cherrypy.response.version

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.

3.3.4. cherrypy.server

3.3.4.1. cherrypy.server.start(initOnly=False, serverClass=_missing)

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.

3.3.4.2. cherrypy.server.blocking

If the "initOnly" argument to server.start is True, this will be False, and vice-versa.

3.3.4.3. cherrypy.server.httpserverclass

Whatever HTTP server class is set in server.start will be stuck in here.

3.3.4.4. cherrypy.server.httpserver

Whatever HTTP server class is set in server.start will be instantiated and stuck in here.

3.3.4.5. cherrypy.server.state

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.

3.3.4.6. cherrypy.server.ready

True if the server is ready to receive requests, false otherwise. Read-only.

3.3.4.7. cherrypy.server.wait()

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.

3.3.4.8. cherrypy.server.start_with_callback(func, args=(), kwargs={}, serverClass=_missing)

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.

3.3.4.9. cherrypy.server.stop()

Stop the CherryPy Server. Well, "suspend" might be a better term—this doesn't terminate the process.

3.3.4.10. cherrypy.server.interrupt

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.

3.3.4.11. cherrypy.server.restart()

Restart the CherryPy Server.

3.3.4.12. cherrypy.server.onStartServerList

A list of functions that will be called when the server starts.

3.3.4.13. cherrypy.server.onStopServerList

A list of functions that will be called when the server stops.

3.3.4.14. cherrypy.server.onStartThreadList

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.

3.3.4.15. cherrypy.server.onStopThreadList

A list of functions that will be called when each request thread is stopped.

3.3.4.16. cherrypy.server.request()

HTTP servers should call this function to hand off the HTTP request to the CherryPy core. There is no return value; instead, the core sets response content in the cherrypy.response object.

3.3.5. cherrypy.config

3.3.5.1. cherrypy.config.get(key, defaultValue = None, returnSection = False)

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.

3.3.5.2. cherrypy.config.getAll(key)

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.

3.3.5.3. cherrypy.config.update(updateMap=None, file=None)

Function to update the configuration map. The "updateMap" argument is a dictionary of the form {'sectionPath' : { } }. The "file" argument is the path to the configuration file.

3.3.6. cherrypy exceptions

3.3.6.1. cherrypy.HTTPError

This exception can be used to automatically send a response using a http status code, with an appropriate error page.

3.3.6.1.1. cherrypy.NotFound

This exception is raised when CherryPy is unable to map a requested path to an internal method. It's a subclass of HTTPError.

3.3.6.2. cherrypy.HTTPRedirect

This exception will force a HTTP redirect.

3.3.6.3. cherrypy.InternalRedirect

This exception will redirect processing to another path within the site (without informing the client).

3.3.7. The CherryPy library

3.3.7.1. cherrypy.lib.cptools
3.3.7.1.1. ExposeItems

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.

3.3.7.1.2. PositionalParametersAware

Utility class that restores positional parameters functionality that was found in 2.0.0-beta.

3.3.7.1.3. getRanges(content_length)

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)].

3.3.7.1.4. serveFile(path, contentType=None, disposition=None, name=None)

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.

3.3.7.2. cherrypy.lib.covercp

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.

3.3.7.3. cherrypy.lib.profiler

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.

3.3.7.4. cherrypy.lib.autoreload

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:

Figure 3.2. The autoreload process

The autoreload process

3.3.8. Special functions and attributes

3.3.8.1. _cpOnError

_cpOnError is a function for handling unanticipated exceptions, whether raised by CherryPy itself, or in user applications. The default simply raises HTTPError(500).

3.3.8.2. _cpFilterList

User defined filters are enabled using the class attribute _cpFilterList. Any filter instances placed in _cpFilterList will be applied to all methods of the class.

3.3.9. Filter API

3.3.9.1. onStartResource
3.3.9.2. beforeRequestBody
3.3.9.3. beforeMain
3.3.9.4. beforeFinalize
3.3.9.5. onEndResource
3.3.9.6. beforeErrorResponse
3.3.9.7. afterErrorResponse

3.4. Filters explained

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:

  • before a request is processed
  • after a request has been processed
  • before a response is sent to the client
  • after a response is sent to the client

3.4.1. Builtin Filters

3.4.1.1. baseurlfilter

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

  • baseUrlFilter.baseUrl
  • baseUrlFilter.useXForwardedHost
3.4.1.2. cachefilter
3.4.1.3. decodingfilter

The decoding filter can be configured to automatically decode incoming requests.

The decodingfilter has the following configuration options:

  • decodingFilter.encoding
3.4.1.4. encodingfilter

The encodingfilter can be configured to automatically encode outgoing responses.

The encodingfilter has the following configuration options:

  • encodingFilter.encoding
  • encodingFilter.mimeTypeList
3.4.1.5. gzipfilter

The gzipfilter will automatically gzip outgoing requests, if it is supported by the client.

The gzipfilter does not have any configuration options.

3.4.1.6. logdebuginfofilter

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:

            3.4.1.7. staticfilter

            The static filter allows CherryPy to serve static files.

            The staticfilter has the following configuration options:

            • staticFilter.file
            • staticFilter.dir
            • staticFilter.root

            3.4.1.8. nsgmlsfilter
            3.4.1.9. tidyfilter

            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:

            • tidyFilter.tmpDir
            • tidyFilter.strictXml, False
            • tidyFilter.tidyPath
            • encodingFilter.errorsToIgnore, []
            3.4.1.10. virtualhostfilter

            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:

            • virtualHostFilter.prefix, '/'
            3.4.1.11. xmlrpcfilter

            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.

            3.4.1.12. sessionauthenticatefilter
            3.4.1.13. sessionfilter
            The Session Filter has its own section

            3.4.2. Writing Filters

            3.4.2.1. Extending basefilter
            3.4.2.2. Defining configurable settings
            3.4.2.3. Pitfalls to avoid

            3.5. Web servers architecure (HTTP servers which CP supplies)

            3.5.1. Design choices

            3.5.2. WSGI server

            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.

            3.5.2.1. mod_python
            3.5.2.2. IIS/ASP
            3.5.2.3. FastCGI
            3.5.2.4. SCGI

            3.5.3. HTTP server

            Appendix A. Appendix

            1. History of CherryPy

            1.1. CherryPy 1

            1.2. CherryPy 2

            1.2.1. CherryPy 2.0

            1.2.2. CherryPy 2.1

            2. Coding style

            3. License

            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:

            • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
            • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
            • Neither the name of the CherryPy Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

            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.