Commits

Robert Brewer  committed 42b3553

Removed deprecated _cphttpserver.py.

  • Participants
  • Parent commits 3b3278f

Comments (0)

Files changed (5)

File CHANGELOG.txt

+2006-02-16:
+    * Removed _cphttpserver, the native HTTP server that was deprecated in CP 2.1 (fumanchu)
+
 2006-01-27:
     * CherryPy-2.2.0beta released
     * Lots of improvements to sessionfilter
     * Added cherrypy.lower_api switch (people get a speed boost if they
     *   set it to True)
 
+2006-01-02:
+    * New _cptree module, with strong encouragement to call tree.mount(Root()[, baseurl]) instead of cherrypy.root = Root().
+
 2005-12-05:
     * Added support for specifying the Content-Type to be used by defaults
     * Added a response headers filter to specify HTTP headers

File cherrypy/_cphttpserver.py

-"""A native HTTP server for CherryPy."""
-
-from BaseHTTPServer import BaseHTTPRequestHandler
-import os
-import Queue
-import socket
-import SocketServer
-import sys
-import threading
-import time
-
-import cherrypy
-from cherrypy import _cputil
-from cherrypy.lib import httptools
-
-
-class CherryHTTPRequestHandler(BaseHTTPRequestHandler):
-    """CherryPy HTTP request handler"""
-    
-    def address_string(self):
-        """ Try to do a reverse DNS based on server.reverse_dns in the config file """
-        if cherrypy.config.get('server.reverse_dns'):
-            return BaseHTTPRequestHandler.address_string(self)
-        else:
-            return self.client_address[0]
-    
-    def _headerlist(self):
-        hlist = []
-        hit = 0
-        for line in self.headers.headers:
-            if line:
-                if line[0] in ' \t':
-                    # Continuation line. Add to previous entry.
-                    if hlist:
-                        hlist[-1][1] += " " + line.lstrip()
-                else:
-                    # New header. Add a new entry. We don't catch
-                    # ValueError here because we trust rfc822.py.
-                    name, value = line.split(":", 1)
-                    hlist.append((name.strip(), value.strip()))
-        return hlist
-    
-    def parse_request(self):
-        # Extended to provide header and body length limits.
-        mhs = int(cherrypy.config.get('server.max_request_header_size',
-                                      500 * 1024))
-        self.rfile = httptools.SizeCheckWrapper(self.rfile, mhs)
-        try:
-            presult = BaseHTTPRequestHandler.parse_request(self)
-        except httptools.MaxSizeExceeded:
-            self.send_error(413, "Request Entity Too Large")
-            cherrypy.log(traceback=True)
-            return False
-        else:
-            if presult:
-                # Request header is parsed
-                # We prepare the SizeCheckWrapper for the request body
-                self.rfile.bytes_read = 0
-                path = self.path
-                if path == "*":
-                    path = "global"
-                mbs = int(cherrypy.config.get('server.max_request_body_size',
-                                              100 * 1024 * 1024, path=path))
-                self.rfile.maxlen = mbs
-        return presult
-    
-    def handle_one_request(self):
-        """Handle a single HTTP request."""
-        
-        self.raw_requestline = self.rfile.readline()
-        if not self.raw_requestline:
-            self.close_connection = 1
-            return
-        if not self.parse_request(): # An error code has been sent, just exit
-            return
-        
-        request = None
-        try:
-            request = cherrypy.server.request(self.client_address,
-                                              self.address_string(), "http")
-            request.multithread = cherrypy.config.get("server.thread_pool") > 1
-            request.multiprocess = False
-            response = request.run(self.raw_requestline, self._headerlist(),
-                                   self.rfile)
-            s, h, b = response.status, response.header_list, response.body
-            exc = None
-        except (KeyboardInterrupt, SystemExit):
-            raise
-        except:
-            tb = _cputil.formatExc()
-            cherrypy.log(tb)
-            if cherrypy.config.get("server.throw_errors", False):
-                msg = "THROWN ERROR: %s" % sys.exc_info()[0].__name__
-                s = "500 Internal Server Error"
-                h = [('Content-Type', 'text/plain'),
-                     ('Content-Length', str(len(msg)))]
-                b = [msg]
-            else:
-                if not cherrypy.config.get("server.show_tracebacks", False):
-                    tb = ""
-                s, h, b = _cputil.bareError(tb)
-        
-        try:
-            wfile = self.wfile
-            wfile.write("%s %s\r\n" % (self.protocol_version, s))
-            
-            has_close_conn = False
-            for name, value in h:
-                wfile.write("%s: %s\r\n" % (name, value))
-                if name.lower == 'connection' and value.lower == 'close':
-                    has_close_conn = True
-            if not has_close_conn:
-                # This server doesn't support persistent connections yet, so we
-                # must add a "Connection: close" header to tell the client that
-                # we will close the connection when we're done sending output.
-                # 
-                # From RFC 2616 sec 14.10:
-                # HTTP/1.1 defines the "close" connection option for the sender
-                # to signal that the connection will be closed after completion
-                # of the response. For example,
-                # 
-                #    Connection: close
-                # 
-                # in either the request or the response header fields indicates
-                # that the connection SHOULD NOT be considered `persistent'
-                # (section 8.1) after the current request/response is complete.
-                # 
-                # HTTP/1.1 applications that do not support persistent connections
-                # MUST include the "close" connection option in every message.
-                wfile.write("Connection: close\r\n")
-            
-            wfile.write("\r\n")
-            for chunk in b:
-                wfile.write(chunk)
-            if request:
-                request.close()
-        except (KeyboardInterrupt, SystemExit), ex:
-            try:
-                if request:
-                    request.close()
-            except:
-                cherrypy.log(traceback=True)
-            raise ex
-        except:
-            cherrypy.log(traceback=True)
-            try:
-                if request:
-                    request.close()
-            except:
-                cherrypy.log(traceback=True)
-            
-            s, h, b = _cputil.bareError()
-            # CherryPy test suite expects bareError body to be output,
-            # so don't call start_response (which, according to PEP 333,
-            # may raise its own error at that point).
-            for chunk in b:
-                wfile.write(chunk)
-        
-        if self.command == "POST":
-            self.connection = self.request
-        
-        # Close the conn, since we do not yet support persistent connections.
-        self.close_connection = 1
-    
-    def log_message(self, format, *args):
-        """ We have to override this to use our own logging mechanism """
-        cherrypy.log(format % args, "HTTP")
-
-
-class CherryHTTPServer(SocketServer.BaseServer):
-    # Subclass BaseServer (instead of BaseHTTPServer.HTTPServer), because
-    # getfqdn call was timing out on localhost when calling gethostbyaddr.
-    
-    ready = False
-    interrupt = None
-    RequestHandlerClass = CherryHTTPRequestHandler
-    allow_reuse_address = True
-    
-    def __init__(self):
-        # SocketServer __init__'s all say "do not override",
-        # but we have to in order to implement SSL and IPv6 support!
-        
-        # Set protocol_version
-        httpproto = cherrypy.config.get('server.protocol_version') or "HTTP/1.0"
-        self.RequestHandlerClass.protocol_version = httpproto
-        
-        self.request_queue_size = cherrypy.config.get('server.socket_queue_size')
-    
-    def server_bind(self):
-        """Called by constructor to bind the socket."""
-        
-        # Select the appropriate server based on config options
-        sockFile = cherrypy.config.get('server.socket_file')
-        if sockFile:
-            # AF_UNIX socket
-            self.address_family = socket.AF_UNIX
-            
-            # So we can reuse the socket
-            try: os.unlink(sockFile)
-            except: pass
-            
-            # So everyone can access the socket
-            try: os.chmod(sockFile, 0777)
-            except: pass
-            
-            self.server_address = sockFile
-            self.socket = socket.socket(self.address_family, self.socket_type)
-            self._server_bind()
-        else:
-            # AF_INET or AF_INET6 socket
-            host = cherrypy.config.get('server.socket_host')
-            port = cherrypy.config.get('server.socket_port')
-            self.server_address = (host, port)
-            
-            try:
-                info = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
-                                          socket.SOCK_STREAM)
-            except socket.gaierror:
-                # Probably a DNS issue.
-                # Must...refuse...temptation..to..guess...
-                self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-                self._server_bind()
-            else:
-                # Get the correct address family for our host (allows IPv6 addresses)
-                for res in info:
-                    af, socktype, proto, canonname, sa = res
-                    self.address_family = af
-                    self.socket_type = socktype
-                    try:
-                        self.socket = socket.socket(af, socktype, proto)
-                        self._server_bind()
-                    except socket.error, msg:
-                        if self.socket:
-                            self.socket.close()
-                        self.socket = None
-                        continue
-                    break
-                if not self.socket:
-                    raise socket.error, msg
-    
-    def _server_bind(self):
-        if self.allow_reuse_address:
-            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        self.socket.bind(self.server_address)
-    
-    def server_activate(self):
-        """Override server_activate to set timeout on our listener socket"""
-        self.socket.settimeout(1)
-        self.socket.listen(self.request_queue_size)
-    
-    def close_request(self, request):
-        """Called to clean up an individual request."""
-        request.close()
-    
-    def get_request(self):
-        # With Python 2.3 it seems that an accept socket in timeout
-        # (nonblocking) mode results in request sockets that are also set
-        # in nonblocking mode. Since that doesn't play well with makefile()
-        # (where wfile and rfile are set in SocketServer.py) we explicitly
-        # set the request socket to blocking
-        request, client_address = self.socket.accept()
-        if hasattr(request, 'setblocking'):
-            request.setblocking(1)
-        return request, client_address
-    
-    def handle_request(self):
-        """Handle one request, possibly blocking."""
-        # Overridden to trap socket.timeout and KeyboardInterrupt/SystemExit.
-        try:
-            request, client_address = self.get_request()
-        except (socket.error, socket.timeout):
-            # The only reason for the timeout is so we can notice keyboard
-            # interrupts on Win32, which don't interrupt accept() by default
-            return
-        
-        try:
-            self.process_request(request, client_address)
-        except (KeyboardInterrupt, SystemExit):
-            self.close_request(request)
-            raise
-        except:
-            self.handle_error(request, client_address)
-            self.close_request(request)
-    
-    def handle_error(self, request, client_address):
-        cherrypy.log(traceback=True)
-    
-    def serve_forever(self):
-        """Override serve_forever to handle shutdown."""
-        self.ready = True
-        while self.ready:
-            if self.interrupt:
-                raise self.interrupt
-            self.handle_request()
-        self.server_close()
-    
-    def start(self):
-        self.server_bind()
-        self.server_activate()
-        self.serve_forever()
-    
-    def server_close(self):
-        self.ready = False
-        self.socket.close()
-    stop = shutdown = server_close
-
-
-class PooledThreadServer(CherryHTTPServer):
-    """A TCP Server using a pool of worker threads. This is superior to the
-       alternatives provided by the Python standard library, which only offer
-       (1) handling a single request at a time, (2) handling each request in
-       a separate thread (via ThreadingMixIn), or (3) handling each request in
-       a separate process (via ForkingMixIn). It's also superior in some ways
-       to the pure async approach used by Twisted because it allows a more
-       straightforward and simple programming model in the face of blocking
-       requests (i.e. you don't have to bother with Deferreds)."""
-    
-    def __init__(self):
-        self.numThreads = cherrypy.config.get('server.thread_pool')
-        self.ThreadClass = ServerThread
-        self.requestQueue = Queue.Queue()
-        self.workerThreads = []
-        CherryHTTPServer.__init__(self)
-    
-    def process_request(self, request, client_address):
-        """Call finish_request."""
-        self.finish_request(request, client_address)
-        # Let the ServerThread close the request when it's finished.
-##      NO!  self.close_request(request)
-    
-    def finish_request(self, request, client_address):
-        """Finish one request by passing it to the Queue."""
-        self.requestQueue.put((request, client_address))
-    
-    def createThread(self):
-        return self.ThreadClass(self.RequestHandlerClass, self.requestQueue, self)
-    
-    def serve_forever(self):
-        """Handle one request at a time until doomsday (or shutdown is called)."""
-        if self.workerThreads == []:
-            for i in xrange(self.numThreads):
-                self.workerThreads.append(self.createThread())
-            for worker in self.workerThreads:
-                worker.start()
-        
-        for worker in self.workerThreads:
-            while not worker.ready:
-                time.sleep(.1)
-        
-        CherryHTTPServer.serve_forever(self)
-    
-    def server_close(self):
-        """Gracefully shutdown a server that is serve_forever()ing."""
-        CherryHTTPServer.server_close(self)
-        
-        # Must shut down threads here so the code that calls
-        # this method can know when all threads are stopped.
-        for worker in self.workerThreads:
-            self.requestQueue.put(_SHUTDOWNREQUEST)
-        current = threading.currentThread()
-        for worker in self.workerThreads:
-            if worker is not current and worker.isAlive:
-                worker.join()
-        self.workerThreads = []
-    stop = shutdown = server_close
-
-
-_SHUTDOWNREQUEST = (0,0)
-
-class ServerThread(threading.Thread):
-    
-    def __init__(self, RequestHandlerClass, requestQueue, server):
-        self.server = server
-        self.ready = False
-        threading.Thread.__init__(self)
-        self.RequestHandlerClass = RequestHandlerClass
-        self.requestQueue = requestQueue
-    
-    def run(self):
-        try:
-            self.ready = True
-            while 1:
-                request, client_address = self.requestQueue.get()
-                if (request, client_address) == _SHUTDOWNREQUEST:
-                    return
-                try:
-                    try:
-                        self.RequestHandlerClass(request, client_address, self)
-                    except (KeyboardInterrupt, SystemExit):
-                        raise
-                    except:
-                        cherrypy.log(traceback=True)
-                finally:
-                    request.close()
-        except (KeyboardInterrupt, SystemExit), exc:
-            self.server.interrupt = exc
-
-
-def embedded_server(handler=None):
-    """Selects and instantiates the appropriate server."""
-    
-    # Select the appropriate server based on config options
-    if cherrypy.config.get('server.thread_pool', 1) > 1:
-        ServerClass = PooledThreadServer
-    else:
-        ServerClass = CherryHTTPServer
-    return ServerClass()
-

File cherrypy/test/test.py

     
     # The first server in the list is the default server.
     available_servers = {'serverless': (0, "Serverless", None),
-                         'native': (1, "Native HTTP Server",
-                                    "cherrypy._cphttpserver.embedded_server"),
-                         'wsgi': (2, "Native WSGI Server",
+                         'wsgi': (1, "Native WSGI Server",
                                   "cherrypy.test.helper.TestWSGI"),
                          }
     default_server = "wsgi"

File cherrypy/test/test_states.py

         run(server, conf)
     _run(None)
     _run("cherrypy._cpwsgi.WSGIServer")
-    _run("cherrypy._cphttpserver.PooledThreadServer")
-    conf['server.thread_pool'] = 1
-    _run("cherrypy._cphttpserver.CherryHTTPServer")
 
 
 def run_localhosts(port):
             print "Testing %s on %s:%s..." % (server or "serverless", host, port)
             run(server, conf)
         _run("cherrypy._cpwsgi.WSGIServer")
-        _run("cherrypy._cphttpserver.PooledThreadServer")
-        conf['server.thread_pool'] = 1
-        _run("cherrypy._cphttpserver.CherryHTTPServer")
 
 
 if __name__ == "__main__":

File docs/book/xml/apireference.xml

-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5b1//EN"
-"http://www.oasis-open.org/docbook/xml/4.5b1/docbookx.dtd">
-<section xmlns:db="http://docbook.org/docbook-ng" xmlns:xi="http://www.w3.org/2001/XInclude"
-         xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:id="apireference">
-    <title>API reference</title>
-    <section id="cherrypy">
-        <title>cherrypy.thread_data</title>
-        <para>This attribute holds attributes that map to this thread only.</para>
-    </section>
-    <section id="cherrypyrequest">
-        <title>cherrypy.request</title>
-        <para>The cherrypy.request object contains request-related objects. Pretty lame description,
-        but that's all it does; it's a big data dump. At the beginning of each HTTP request, the
-        existing request object is destroyed, and a new one is created, (one request object for each
-        thread). Therefore, CherryPy (and you yourself) can stick data into cherrypy.request and not
-        worry about it conflicting with other requests.</para>
-        <section>
-            <title>cherrypy.request.remoteAddr</title>
-            <para>This attribute is a string containing the IP address of the client. It will be an
-            empty string if it is not available.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.remotePort</title>
-            <para>This attribute is an int containing the TCP port number of the client. It will be
-            -1 if it is not available.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.remoteHost</title>
-            <para>This attribute is a string containing the remote hostname of the client.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.headers</title>
-            <para>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.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.header_list</title>
-            <para>This attribute is a list of (header, value) tuples containing the received HTTP
-            headers. In general, you probably want to use headers instead; this is only here in case
-            you need to inspect duplicates in the request headers.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.requestLine</title>
-            <para>This attribute is a string containing the first line of the raw HTTP request; for
-            example, "GET /path/page HTTP/1.1".</para>
-        </section>
-        <section>
-            <title>cherrypy.request.simple_cookie</title>
-            <para>This attribute is a SimpleCookie instance from the standard library's Cookie module
-            which contains the incoming cookie values from the client.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.rfile</title>
-            <para>This attribute is the input stream to the client, if applicable. See
-            cherrypy.request.processRequestBody for more information.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.body</title>
-            <para>This attribute is the request entity body, if applicable. See
-            cherrypy.request.processRequestBody for more information.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.processRequestBody</title>
-            <para>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.params; 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.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.method</title>
-            <para>This attribute is a string containing the HTTP request method, such as GET or
-            POST.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.protocol</title>
-            <para>This attribute is a string containing the HTTP protocol of the request in the form
-            of HTTP/x.x</para>
-        </section>
-        <section>
-            <title>cherrypy.request.version</title>
-            <para>This attribute is a Version object which represents the HTTP protocol. It's the
-            same os request.protocol, but allows easy comparisons like <code>if
-            cherrypy.request.version &gt;= "1.1": do_http_1_1_thing</code>.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.wsgi_environ</title>
-            <para>This attribute is a dictionary containing the WSGI environment for the request. In
-            non-WSGI settings (i.e., running under _cphttpserver), it is absent.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.query_string</title>
-            <para>This attribute is a string containing the query string of the request (the part of
-            the URL following '?').</para>
-        </section>
-        <section>
-            <title>cherrypy.request.path</title>
-            <para>This attribute is a string containing the path of the resource the client
-            requested.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.params</title>
-            <para>This attribute is a dictionary containing the query string and POST arguments of
-            this request.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.base</title>
-            <para>This attribute is a string containing the root URL of the server. By default, it is
-            equal to request.scheme://request.headers['Host'].</para>
-        </section>
-        <section>
-            <title>cherrypy.request.browser_url</title>
-            <para>This attribute is a string containing the URL the client requested. By default, it
-            is equal to <code>request.base + request.path</code>, plus the querystring, if
-            provided.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.objectPath</title>
-            <para>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.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.originalPath</title>
-            <para>This attribute is a string containing the original value of cherrypy.request.path,
-            in case it is modified by a filter during the request.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.originalParamMap</title>
-            <para>This attribute is a string containing the original value of
-            cherrypy.request.params, in case it is modified by a filter during the request.</para>
-        </section>
-        <section>
-            <title>cherrypy.request.scheme</title>
-            <para>This attribute is a string containing the URL scheme used in this request. It is
-            either "http" or "https".</para>
-        </section>
-    </section>
-    <section id="cherrypyresponse">
-        <title>cherrypy.response</title>
-        <para>The cherrypy.response object contains response-related objects. Pretty lame
-        description, but that's all it does; it's a big data dump. At the beginning of each HTTP
-        request, the existing response object is destroyed, and a new one is created, (one response
-        object for each thread). Therefore, CherryPy (and you yourself) can stick data into
-        cherrypy.response and not worry about it conflicting with other requests.</para>
-        <section>
-            <title>cherrypy.response.headers</title>
-            <para>This attribute is a dictionary with automatically titled keys (e.g.,
-            "Content-Length"). It holds all outgoing HTTP headers to the client.</para>
-        </section>
-        <section>
-            <title>cherrypy.response.header_list</title>
-            <para>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 header_list. In general, you should use request.headers
-            instead.</para>
-        </section>
-        <section>
-            <title>cherrypy.response.simple_cookie</title>
-            <para>This attribute is a SimpleCookie instance from the standard library's Cookie
-            module. It contains the outgoing cookie values.</para>
-        </section>
-        <section>
-            <title>cherrypy.response.body</title>
-            <para>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.</para>
-        </section>
-        <section>
-            <title>cherrypy.response.status</title>
-            <para>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.</para>
-        </section>
-        <section>
-            <title>cherrypy.response.version</title>
-            <para>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 <emphasis>available</emphasis>
-            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.</para>
-        </section>
-    </section>
-    <section id="cherrypyserver">
-        <title>cherrypy.server</title>
-        <section>
-            <title>cherrypy.server.start(init_only = False, server_class = _missing)</title>
-            <para>Start the CherryPy Server. Simple websites may call this without any arguments, to
-            run the default server. If init_only 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.</para>
-            <para>Use the server_class 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):</para>
-            <itemizedlist>
-                <listitem>
-                    <para><code>cherrypy._cphttpserver.CherryHTTPServer</code>: this will load the
-                    old, single-threaded built-in HTTP server. This server is deprecated and will
-                    probably be removed in CherryPy 2.2.</para>
-                </listitem>
-                <listitem>
-                    <para><code>cherrypy._cphttpserver.PooledThreadServer</code>: this will load the
-                    old, multi-threaded built-in HTTP server. This server is deprecated and will
-                    probably be removed in CherryPy 2.2.</para>
-                </listitem>
-                <listitem>
-                    <para><code>cherrypy._cphttpserver.embedded_server</code>: use this to
-                    automatically select between the CherryHTTPServer and the PooledThreadServer
-                    based on the value of config.get("server.thread_pool") and
-                    config.get("server.socket_file").</para>
-                </listitem>
-                <listitem>
-                    <para><code>None</code>: this will not load any HTTP server. Note that this is
-                    not the default; the default (if server_class is not given) is to load the
-                    WSGIServer.</para>
-                </listitem>
-                <listitem>
-                    <para>Any other class (or dotted-name string): load a custom HTTP server.</para>
-                </listitem>
-            </itemizedlist>
-            <para>You <emphasis>must</emphasis> call this function from Python's main thread, and set
-            init_only 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.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.blocking</title>
-            <para>If the "init_only" argument to server.start is True, this will be False, and
-            vice-versa.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.httpserverclass</title>
-            <para>Whatever HTTP server class is set in server.start will be stuck in here.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.httpserver</title>
-            <para>Whatever HTTP server class is set in server.start will be instantiated and stuck in
-            here.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.state</title>
-            <para>One of three values, indicating the state of the server: <itemizedlist>
-                    <listitem>
-                        <para>STOPPED = 0: The server hasn't been started, and will not accept
-                        requests.</para>
-                    </listitem>
-                    <listitem>
-                        <para>STARTING = None: The server is in the process of starting, or an error
-                        occured while trying to start the server.</para>
-                    </listitem>
-                    <listitem>
-                        <para>STARTED = 1: The server has started (including an HTTP server if
-                        requested), and is ready to receive requests.</para>
-                    </listitem>
-                </itemizedlist></para>
-        </section>
-        <section>
-            <title>cherrypy.server.ready</title>
-            <para>True if the server is ready to receive requests, false otherwise. Read-only.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.wait()</title>
-            <para>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.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.start_with_callback(func, args=(), kwargs={}, server_class =
-            _missing)</title>
-            <para>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.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.stop()</title>
-            <para>Stop the CherryPy Server. Well, "suspend" might be a better term—this doesn't
-            terminate the process.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.interrupt</title>
-            <para>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.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.restart()</title>
-            <para>Restart the CherryPy Server.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.on_start_server_list</title>
-            <para>A list of functions that will be called when the server starts.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.on_stop_server_list</title>
-            <para>A list of functions that will be called when the server stops.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.on_start_thread_list</title>
-            <para>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 on_start_thread_list functions upon the first request
-            using each distinct thread.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.on_stop_thread_list</title>
-            <para>A list of functions that will be called when each request thread is stopped.</para>
-        </section>
-        <section>
-            <title>cherrypy.server.request()</title>
-            <para>HTTP servers should call this function to create a new Request and Response object.
-            The return value is the Request object; call its <code>run</code> method to have the
-            CherryPy core process the request data and populate the response.</para>
-        </section>
-    </section>
-    <section id="cherrypyconfig">
-        <title>cherrypy.config</title>
-        <section>
-            <title>cherrypy.config.get(key, defaultValue = None, returnSection = False)</title>
-            <para>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.</para>
-        </section>
-        <section>
-            <title>cherrypy.config.getAll(key)</title>
-            <para>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.</para>
-        </section>
-        <section>
-            <title>cherrypy.config.update(updateMap=None, file=None)</title>
-            <para>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.</para>
-        </section>
-        <section>
-            <title>cherrypy.config.environments</title>
-            <para>Dict containing config defaults for each named server.environment.</para>
-        </section>
-    </section>
-    <section>
-        <title>cherrypy.tree</title>
-        <para>The Tree class is used to keep track of where applications are mounted. To "mount" an
-        application means to have its root respond to a URL other than "/". By using
-        <code>cherrypy.tree</code>, you can easily mount applications and remember where you mounted
-        them!</para>
-        <section>
-            <title>cherrypy.tree.mount(app_root, baseurl=None, conf=None)</title>
-            <para>Function to mount a tree of objects at the given baseurl, using the given
-            configuration dict or filename. If baseurl is None or missing, it is assumed to be "/"
-            unless the config specifies <code>[global] mount_point = "/path/to/approot"</code>. If
-            conf is not None, then each of its sections (which should be a relative URL, like
-            "/skins/deepblue/main") will be prefixed with the baseurl, so that config lookups are
-            also "mounted" at the base URL.</para>
-            <para>Note that, by using tree.mount, your approot may not be found at cherrypy.root;
-            there may be several "dummy" objects placed in-between cherrypy.root and your
-            application's root instance.</para>
-        </section>
-        <section>
-            <title>cherrypy.tree.mount_points</title>
-            <para>A dict of the form {baseurl: approot-instance}.</para>
-        </section>
-        <section>
-            <title>cherrypy.tree.mount_point(path=None)</title>
-            <para>A method which finds the appropriate baseurl for a given path. If path is None or
-            missing, cherrypy.request.object_path is used. If multiple applications "contain" the
-            given path, the longer baseurl is returned. That is, if App1 is mounted at "/" and App2
-            is mounted at "/path/to/app", then
-            <code>cherrypy.tree.mount_point("/path/to/app/main")</code> will return
-            "/path/to/app".</para>
-            <para>Once you have obtained the baseurl using mount_point, you can obtain a reference to
-            the application root object by looking up
-            <code>cherrypy.tree.mount_points[baseurl]</code>.</para>
-        </section>
-        <section>
-            <title>cherrypy.tree.url(path, mount_point=None)</title>
-            <para>Prefixes the given path with the given mount_point, which isn't very exciting
-            unless mount_point is None or missing, in which case, cherrypy.request.object_path will
-            be used to find the current mount_point and prefix <emphasis>that</emphasis> to the given
-            path.</para>
-        </section>
-    </section>
-    <section id="exceptions">
-        <title>cherrypy exceptions</title>
-        <section>
-            <title>cherrypy.HTTPError</title>
-            <para>This exception can be used to automatically send a response using a http status
-            code, with an appropriate error page.</para>
-            <section>
-                <title>cherrypy.NotFound</title>
-                <para>This exception is raised when CherryPy is unable to map a requested path to an
-                internal method. It's a subclass of HTTPError (404).</para>
-            </section>
-        </section>
-        <section>
-            <title>cherrypy.HTTPRedirect</title>
-            <para>This exception will force a HTTP redirect.</para>
-        </section>
-        <section>
-            <title>cherrypy.InternalRedirect</title>
-            <para>This exception will redirect processing to another path within the site (without
-            informing the client). Provide the new path as an argument when raising the exception.
-            You may also provide a second "params" argument which will replace the current request
-            params (usually a dict, but you may also supply a GET-param-style string). This exception
-            is only handled from within page handlers and before_main filter methods.</para>
-        </section>
-    </section>
-    <section id="lib">
-        <title>The CherryPy library</title>
-        <section>
-            <title>cherrypy.lib.cptools</title>
-            <section>
-                <title>ExposeItems</title>
-                <para>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.</para>
-            </section>
-            <section>
-                <title>PositionalParametersAware</title>
-                <para>Utility class that restores positional parameters functionality that was found
-                in 2.0.0-beta.</para>
-            </section>
-            <section>
-                <title>getAccept(headername)</title>
-                <para>Returns a list of AcceptValue objects from the specified Accept-* header (or
-                None if the header is not present). The list is sorted so that the most-preferred
-                values are first in the list.</para>
-                <para>Each AcceptValue object has a <code>value</code> attribute, a string which is
-                the value itself. For example, if <code>headername</code> is "Accept-Encoding", the
-                <code>value</code> attribute might be "gzip". It also has a (read-only)
-                <code>qvalue</code> attribute, a float between 0 and 1 which specifies the client's
-                preference for the value; higher numbers are preferred. Finally, each AcceptValue
-                also has a <code>params</code> attribute, a dict; for most headers, this dict will
-                only possess the original "q" value as a string.</para>
-                <para>If <code>headername</code> is "Accept" (the default), then the params attribute
-                may contain extra parameters which further differentiate the value. In addition,
-                <code>params["q"]</code> may itself be an AcceptValue object, with its own
-                <code>params</code> dict. Don't ask us why; ask the authors of the HTTP spec.</para>
-            </section>
-            <section>
-                <title>getRanges(content_length)</title>
-                <para>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)].</para>
-            </section>
-            <section>
-                <title>headers</title>
-                <para>A subclass of Python's builtin <code>dict</code> class; CherryPy's default
-                <code>request.headers</code> and <code>response.headers</code> objects are instances
-                of this class. The keys are automatically titled (<code>str(key).title()</code>) in
-                order to provide case-insensitive comparisons and avoid duplicates.</para>
-            </section>
-            <section>
-                <title>parseRequestLine(requestLine)</title>
-                <para>Returns (<code>method, path, querystring, protocol</code>) from an HTTP
-                requestLine. The default Request processor calls this function.</para>
-            </section>
-            <section>
-                <title>parseQueryString(query_string, keep_blank_values=True)</title>
-                <para>Returns a dict of <code>{'key': 'value'}</code> pairs from an HTTP "key=value"
-                query string. Also handles server-side image map query strings. The default Request
-                processor calls this function.</para>
-            </section>
-            <section>
-                <title>paramsFromCGIForm(form)</title>
-                <para>Returns a dict of <code>{'key': ''value'}</code> pairs from a
-                <code>cgi.FieldStorage</code> object. The default Request processor calls this
-                function.</para>
-            </section>
-            <section>
-                <title>serveFile(path, contentType=None, disposition=None, name=None)</title>
-                <para>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 "&lt;disposition&gt;;
-                filename=&lt;name&gt;". If name is None, it will be set to the basename of path. If
-                disposition is None, no Content-Disposition header will be written.</para>
-            </section>
-        </section>
-        <section>
-            <title>cherrypy.lib.covercp</title>
-            <para>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' <ulink url="???">original implementation</ulink> or
-            Ned Batchelder's <ulink url="http://www.nedbatchelder.com/code/modules/coverage.html">
-            enhanced version</ulink>.</para>
-            <para>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.</para>
-        </section>
-        <section>
-            <title>cherrypy.lib.profiler</title>
-            <para>You can profile any of your page handlers (exposed methods) as follows:</para>
-            <example>
-                <title>Profiling example</title>
-                <programlisting><code>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()</code></programlisting>
-            </example>
-            <para>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.</para>
-            <para>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.</para>
-        </section>
-        <section>
-            <title>cherrypy.lib.autoreload</title>
-            <para>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>
-                    <title>The autoreload process</title>
-                    <mediaobject>
-                        <imageobject>
-                            <imagedata fileref="autoreload.gif" format="GIF" />
-                        </imageobject>
-                    </mediaobject>
-                </figure></para>
-        </section>
-    </section>
-    <section id="specialfunctions">
-        <title>Special functions and attributes</title>
-        <section>
-            <title>_cp_on_error</title>
-            <para>_cp_on_error is a function for handling unanticipated exceptions, whether raised by
-            CherryPy itself, or in user applications. The default simply responds as if
-            HTTPError(500) had been raised.</para>
-        </section>
-        <section>
-            <title>_cp_on_http_error</title>
-            <para>_cp_on_http_error handles HTTPError responses, setting cherrypy.response.status,
-            headers, and body.</para>
-        </section>
-        <section>
-            <title>_cp_filters</title>
-            <para>User defined filters are enabled using the class attribute _cp_filters. Any filter
-            instances placed in _cp_filters will be applied to all methods of the class.</para>
-        </section>
-        <section>
-            <title>_cp_log_access</title>
-            <para>Function to log HTTP requests into the access.log file.</para>
-        </section>
-        <section>
-            <title>_cp_log_message</title>
-            <para>Function to log errors into the error.log file. The <code>cherrypy.log</code>
-            function is syntactic sugar for this one.</para>
-        </section>
-    </section>
-    <section id="filters">
-        <title>Filter API</title>
-        <para>CherryPy provides a set of hooks which are called at specific places during the request
-        process. A filter should inherit from the BaseFilter class and implement the hooks it
-        requires to add extra code during the process. CherryPy will go through all the filters which
-        are on (buil-in and user defined) for that requested path and call all hooks that are
-        implemented by each filter.</para>
-        <section>
-            <title>on_start_resource</title>
-            <para>This hook is being called righ at the beginning of the request process. The only
-            work CherryPy has done when this hook is called is to parse the first line of the HTTP
-            request. This is needed so that filters have access to the object path translated from
-            the path specified in the HTTP request.</para>
-            <para>This hook is always called.</para>
-        </section>
-        <section>
-            <title>before_request_body</title>
-            <para>This hook is being called right after CherryPy has parse the HTTP request headers
-            but before it tries to parse the request body. If a filter which implements that hook
-            sets cherrypy.request.processRequestBody to False, CherryPy will not parse the request
-            body at all. This can be handy when you know your user agent returns the data in a form
-            that the default CherryPy request body parsing function cannot understand.</para>
-            <para>For example, assuming your user agent returns you a request body which is an XML
-            string unquoted, you may want a filter to parse that XML string and generates an XML DOM
-            instance. Then the filter could add that instance to the cherrypy.request.params which in
-            turns would be passed to your page handler like if it had actually been sent like that
-            through the HTTP request. Therefore your filter has turned the XML string into an XML DOM
-            instance transparently and makes your life easier. In that case you do not want CherryPy
-            to parse the request body. It could also be used to scan the request body before it is
-            being processed any further and decide to reject it if needed.</para>
-            <para>This hook is not called if an error occurs during the process before hand.</para>
-        </section>
-        <section>
-            <title>before_main</title>
-            <para>This hook is called right before your page handler (exposed callable) is being
-            called by CherryPy. It can be handy if considering HTTP request headers or body you may
-            want not to call the page handler at all, then you would have to set
-            cherrypy.request.executeMain to False.</para>
-            <para>This hook is not called if an error occurs during the process before hand.</para>
-        </section>
-        <section>
-            <title>before_finalize</title>
-            <para>This hook is called right after the page handler has been processed (depending on
-            the before_main hook behavior) and before CherryPy formats the final respone object. It
-            helps you for example to check for what could have been returned by your page handler and
-            change some headers of needed.</para>
-            <para>This hook is not called if an error occurs during the process before hand.</para>
-        </section>
-        <section>
-            <title>on_end_resource</title>
-            <para>This hook is called at the end of the process so that you can finely tweak your
-            HTTP response if needed (eg adding headers to the cherrypy.response.header_list). Note
-            that cherrypy.response.headers will not be processed any longer at that stage.</para>
-            <para>This hook is always called.</para>
-        </section>
-        <section>
-            <title>before_error_response</title>
-            <para>This hook is called when an error has occured during the request processing. It
-            allows you to called code before the _cp_on_error handler is being called as well as the
-            response finalizing stage.</para>
-        </section>
-        <section>
-            <title>after_error_response</title>
-            <para>This hook is called when an error has occured during the request processing. It
-            allows you to call code after the _cp_on_error handler is being called as well as the
-            response finalizing stage.</para>
-        </section>
-    </section>
-</section>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5b1//EN"
+"http://www.oasis-open.org/docbook/xml/4.5b1/docbookx.dtd">
+<section xmlns:db="http://docbook.org/docbook-ng" xmlns:xi="http://www.w3.org/2001/XInclude"
+         xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:id="apireference">
+    <title>API reference</title>
+    <section id="cherrypy">
+        <title>cherrypy.thread_data</title>
+        <para>This attribute holds attributes that map to this thread only.</para>
+    </section>
+    <section id="cherrypyrequest">
+        <title>cherrypy.request</title>
+        <para>The cherrypy.request object contains request-related objects. Pretty lame description,
+        but that's all it does; it's a big data dump. At the beginning of each HTTP request, the
+        existing request object is destroyed, and a new one is created, (one request object for each
+        thread). Therefore, CherryPy (and you yourself) can stick data into cherrypy.request and not
+        worry about it conflicting with other requests.</para>
+        <section>
+            <title>cherrypy.request.remoteAddr</title>
+            <para>This attribute is a string containing the IP address of the client. It will be an
+            empty string if it is not available.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.remotePort</title>
+            <para>This attribute is an int containing the TCP port number of the client. It will be
+            -1 if it is not available.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.remoteHost</title>
+            <para>This attribute is a string containing the remote hostname of the client.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.headers</title>
+            <para>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.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.header_list</title>
+            <para>This attribute is a list of (header, value) tuples containing the received HTTP
+            headers. In general, you probably want to use headers instead; this is only here in case
+            you need to inspect duplicates in the request headers.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.requestLine</title>
+            <para>This attribute is a string containing the first line of the raw HTTP request; for
+            example, "GET /path/page HTTP/1.1".</para>
+        </section>
+        <section>
+            <title>cherrypy.request.simple_cookie</title>
+            <para>This attribute is a SimpleCookie instance from the standard library's Cookie module
+            which contains the incoming cookie values from the client.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.rfile</title>
+            <para>This attribute is the input stream to the client, if applicable. See
+            cherrypy.request.processRequestBody for more information.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.body</title>
+            <para>This attribute is the request entity body, if applicable. See
+            cherrypy.request.processRequestBody for more information.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.processRequestBody</title>
+            <para>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.params; 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.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.method</title>
+            <para>This attribute is a string containing the HTTP request method, such as GET or
+            POST.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.protocol</title>
+            <para>This attribute is a string containing the HTTP protocol of the request in the form
+            of HTTP/x.x</para>
+        </section>
+        <section>
+            <title>cherrypy.request.version</title>
+            <para>This attribute is a Version object which represents the HTTP protocol. It's the
+            same os request.protocol, but allows easy comparisons like <code>if
+            cherrypy.request.version &gt;= "1.1": do_http_1_1_thing</code>.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.wsgi_environ</title>
+            <para>This attribute is a dictionary containing the WSGI environment for the request. In
+            non-WSGI settings (i.e., custom HTTP servers), it is absent.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.query_string</title>
+            <para>This attribute is a string containing the query string of the request (the part of
+            the URL following '?').</para>
+        </section>
+        <section>
+            <title>cherrypy.request.path</title>
+            <para>This attribute is a string containing the path of the resource the client
+            requested.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.params</title>
+            <para>This attribute is a dictionary containing the query string and POST arguments of
+            this request.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.base</title>
+            <para>This attribute is a string containing the root URL of the server. By default, it is
+            equal to request.scheme://request.headers['Host'].</para>
+        </section>
+        <section>
+            <title>cherrypy.request.browser_url</title>
+            <para>This attribute is a string containing the URL the client requested. By default, it
+            is equal to <code>request.base + request.path</code>, plus the querystring, if
+            provided.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.objectPath</title>
+            <para>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.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.originalPath</title>
+            <para>This attribute is a string containing the original value of cherrypy.request.path,
+            in case it is modified by a filter during the request.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.originalParamMap</title>
+            <para>This attribute is a string containing the original value of
+            cherrypy.request.params, in case it is modified by a filter during the request.</para>
+        </section>
+        <section>
+            <title>cherrypy.request.scheme</title>
+            <para>This attribute is a string containing the URL scheme used in this request. It is
+            either "http" or "https".</para>
+        </section>
+    </section>
+    <section id="cherrypyresponse">
+        <title>cherrypy.response</title>
+        <para>The cherrypy.response object contains response-related objects. Pretty lame
+        description, but that's all it does; it's a big data dump. At the beginning of each HTTP
+        request, the existing response object is destroyed, and a new one is created, (one response
+        object for each thread). Therefore, CherryPy (and you yourself) can stick data into
+        cherrypy.response and not worry about it conflicting with other requests.</para>
+        <section>
+            <title>cherrypy.response.headers</title>
+            <para>This attribute is a dictionary with automatically titled keys (e.g.,
+            "Content-Length"). It holds all outgoing HTTP headers to the client.</para>
+        </section>
+        <section>
+            <title>cherrypy.response.header_list</title>
+            <para>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 header_list. In general, you should use request.headers
+            instead.</para>
+        </section>
+        <section>
+            <title>cherrypy.response.simple_cookie</title>
+            <para>This attribute is a SimpleCookie instance from the standard library's Cookie
+            module. It contains the outgoing cookie values.</para>
+        </section>
+        <section>
+            <title>cherrypy.response.body</title>
+            <para>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.</para>
+        </section>
+        <section>
+            <title>cherrypy.response.status</title>
+            <para>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.</para>
+        </section>
+        <section>
+            <title>cherrypy.response.version</title>
+            <para>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 <emphasis>available</emphasis>
+            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.</para>
+        </section>
+    </section>
+    <section id="cherrypyserver">
+        <title>cherrypy.server</title>
+        <section>
+            <title>cherrypy.server.start(init_only = False, server_class = _missing)</title>
+            <para>Start the CherryPy Server. Simple websites may call this without any arguments, to
+            run the default server. If init_only 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.</para>
+            <para>Use the server_class 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):</para>
+            <itemizedlist>
+                <listitem>
+                    <para><code>None</code>: this will not load any HTTP server. Note that this is
+                    not the default; the default (if server_class is not given) is to load the
+                    WSGIServer.</para>
+                </listitem>
+                <listitem>
+                    <para>Any other class (or dotted-name string): load a custom HTTP server.</para>
+                </listitem>
+            </itemizedlist>
+            <para>You <emphasis>must</emphasis> call this function from Python's main thread, and set
+            init_only 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.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.blocking</title>
+            <para>If the "init_only" argument to server.start is True, this will be False, and
+            vice-versa.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.httpserverclass</title>
+            <para>Whatever HTTP server class is set in server.start will be stuck in here.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.httpserver</title>
+            <para>Whatever HTTP server class is set in server.start will be instantiated and stuck in
+            here.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.state</title>
+            <para>One of three values, indicating the state of the server: <itemizedlist>
+                    <listitem>
+                        <para>STOPPED = 0: The server hasn't been started, and will not accept
+                        requests.</para>
+                    </listitem>
+                    <listitem>
+                        <para>STARTING = None: The server is in the process of starting, or an error
+                        occured while trying to start the server.</para>
+                    </listitem>
+                    <listitem>
+                        <para>STARTED = 1: The server has started (including an HTTP server if
+                        requested), and is ready to receive requests.</para>
+                    </listitem>
+                </itemizedlist></para>
+        </section>
+        <section>
+            <title>cherrypy.server.ready</title>
+            <para>True if the server is ready to receive requests, false otherwise. Read-only.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.wait()</title>
+            <para>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.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.start_with_callback(func, args=(), kwargs={}, server_class =
+            _missing)</title>
+            <para>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.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.stop()</title>
+            <para>Stop the CherryPy Server. Well, "suspend" might be a better term—this doesn't
+            terminate the process.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.interrupt</title>
+            <para>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.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.restart()</title>
+            <para>Restart the CherryPy Server.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.on_start_server_list</title>
+            <para>A list of functions that will be called when the server starts.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.on_stop_server_list</title>
+            <para>A list of functions that will be called when the server stops.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.on_start_thread_list</title>
+            <para>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 on_start_thread_list functions upon the first request
+            using each distinct thread.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.on_stop_thread_list</title>
+            <para>A list of functions that will be called when each request thread is stopped.</para>
+        </section>
+        <section>
+            <title>cherrypy.server.request()</title>
+            <para>HTTP servers should call this function to create a new Request and Response object.
+            The return value is the Request object; call its <code>run</code> method to have the
+            CherryPy core process the request data and populate the response.</para>
+        </section>
+    </section>
+    <section id="cherrypyconfig">
+        <title>cherrypy.config</title>
+        <section>
+            <title>cherrypy.config.get(key, defaultValue = None, returnSection = False)</title>
+            <para>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.</para>
+        </section>
+        <section>
+            <title>cherrypy.config.getAll(key)</title>
+            <para>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.</para>
+        </section>
+        <section>
+            <title>cherrypy.config.update(updateMap=None, file=None)</title>
+            <para>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.</para>
+        </section>
+        <section>
+            <title>cherrypy.config.environments</title>
+            <para>Dict containing config defaults for each named server.environment.</para>
+        </section>
+    </section>
+    <section>
+        <title>cherrypy.tree</title>
+        <para>The Tree class is used to keep track of where applications are mounted. To "mount" an
+        application means to have its root respond to a URL other than "/". By using
+        <code>cherrypy.tree</code>, you can easily mount applications and remember where you mounted
+        them!</para>
+        <section>
+            <title>cherrypy.tree.mount(app_root, baseurl=None, conf=None)</title>
+            <para>Function to mount a tree of objects at the given baseurl, using the given
+            configuration dict or filename. If baseurl is None or missing, it is assumed to be "/"
+            unless the config specifies <code>[global] mount_point = "/path/to/approot"</code>. If
+            conf is not None, then each of its sections (which should be a relative URL, like
+            "/skins/deepblue/main") will be prefixed with the baseurl, so that config lookups are
+            also "mounted" at the base URL.</para>
+            <para>Note that, by using tree.mount, your approot may not be found at cherrypy.root;
+            there may be several "dummy" objects placed in-between cherrypy.root and your
+            application's root instance.</para>
+        </section>
+        <section>
+            <title>cherrypy.tree.mount_points</title>
+            <para>A dict of the form {baseurl: approot-instance}.</para>
+        </section>
+        <section>
+            <title>cherrypy.tree.mount_point(path=None)</title>
+            <para>A method which finds the appropriate baseurl for a given path. If path is None or
+            missing, cherrypy.request.object_path is used. If multiple applications "contain" the
+            given path, the longer baseurl is returned. That is, if App1 is mounted at "/" and App2
+            is mounted at "/path/to/app", then
+            <code>cherrypy.tree.mount_point("/path/to/app/main")</code> will return
+            "/path/to/app".</para>
+            <para>Once you have obtained the baseurl using mount_point, you can obtain a reference to
+            the application root object by looking up
+            <code>cherrypy.tree.mount_points[baseurl]</code>.</para>
+        </section>
+        <section>
+            <title>cherrypy.tree.url(path, mount_point=None)</title>
+            <para>Prefixes the given path with the given mount_point, which isn't very exciting
+            unless mount_point is None or missing, in which case, cherrypy.request.object_path will
+            be used to find the current mount_point and prefix <emphasis>that</emphasis> to the given
+            path.</para>
+        </section>
+    </section>
+    <section id="exceptions">
+        <title>cherrypy exceptions</title>
+        <section>
+            <title>cherrypy.HTTPError</title>
+            <para>This exception can be used to automatically send a response using a http status
+            code, with an appropriate error page.</para>
+            <section>
+                <title>cherrypy.NotFound</title>
+                <para>This exception is raised when CherryPy is unable to map a requested path to an
+                internal method. It's a subclass of HTTPError (404).</para>
+            </section>
+        </section>
+        <section>
+            <title>cherrypy.HTTPRedirect</title>
+            <para>This exception will force a HTTP redirect.</para>
+        </section>
+        <section>
+            <title>cherrypy.InternalRedirect</title>
+            <para>This exception will redirect processing to another path within the site (without
+            informing the client). Provide the new path as an argument when raising the exception.
+            You may also provide a second "params" argument which will replace the current request
+            params (usually a dict, but you may also supply a GET-param-style string). This exception
+            is only handled from within page handlers and before_main filter methods.</para>
+        </section>
+    </section>
+    <section id="lib">
+        <title>The CherryPy library</title>
+        <section>
+            <title>cherrypy.lib.cptools</title>
+            <section>
+                <title>ExposeItems</title>
+                <para>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.</para>
+            </section>
+            <section>
+                <title>PositionalParametersAware</title>
+                <para>Utility class that restores positional parameters functionality that was found
+                in 2.0.0-beta.</para>
+            </section>
+            <section>
+                <title>getAccept(headername)</title>
+                <para>Returns a list of AcceptValue objects from the specified Accept-* header (or
+                None if the header is not present). The list is sorted so that the most-preferred
+                values are first in the list.</para>
+                <para>Each AcceptValue object has a <code>value</code> attribute, a string which is
+                the value itself. For example, if <code>headername</code> is "Accept-Encoding", the
+                <code>value</code> attribute might be "gzip". It also has a (read-only)
+                <code>qvalue</code> attribute, a float between 0 and 1 which specifies the client's
+                preference for the value; higher numbers are preferred. Finally, each AcceptValue
+                also has a <code>params</code> attribute, a dict; for most headers, this dict will
+                only possess the original "q" value as a string.</para>
+                <para>If <code>headername</code> is "Accept" (the default), then the params attribute
+                may contain extra parameters which further differentiate the value. In addition,
+                <code>params["q"]</code> may itself be an AcceptValue object, with its own
+                <code>params</code> dict. Don't ask us why; ask the authors of the HTTP spec.</para>
+            </section>
+            <section>
+                <title>getRanges(content_length)</title>
+                <para>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)].</para>
+            </section>
+            <section>
+                <title>headers</title>
+                <para>A subclass of Python's builtin <code>dict</code> class; CherryPy's default
+                <code>request.headers</code> and <code>response.headers</code> objects are instances
+                of this class. The keys are automatically titled (<code>str(key).title()</code>) in
+                order to provide case-insensitive comparisons and avoid duplicates.</para>
+            </section>
+            <section>
+                <title>parseRequestLine(requestLine)</title>
+                <para>Returns (<code>method, path, querystring, protocol</code>) from an HTTP
+                requestLine. The default Request processor calls this function.</para>
+            </section>
+            <section>
+                <title>parseQueryString(query_string, keep_blank_values=True)</title>
+                <para>Returns a dict of <code>{'key': 'value'}</code> pairs from an HTTP "key=value"
+                query string. Also handles server-side image map query strings. The default Request
+                processor calls this function.</para>
+            </section>
+            <section>
+                <title>paramsFromCGIForm(form)</title>
+                <para>Returns a dict of <code>{'key': ''value'}</code> pairs from a
+                <code>cgi.FieldStorage</code> object. The default Request processor calls this
+                function.</para>
+            </section>
+            <section>
+                <title>serveFile(path, contentType=None, disposition=None, name=None)</title>
+                <para>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 "&lt;disposition&gt;;
+                filename=&lt;name&gt;". If name is None, it will be set to the basename of path. If
+                disposition is None, no Content-Disposition header will be written.</para>
+            </section>
+        </section>
+        <section>
+            <title>cherrypy.lib.covercp</title>
+            <para>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' <ulink url="???">original implementation</ulink> or
+            Ned Batchelder's <ulink url="http://www.nedbatchelder.com/code/modules/coverage.html">
+            enhanced version</ulink>.</para>
+            <para>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.</para>
+        </section>
+        <section>
+            <title>cherrypy.lib.profiler</title>
+            <para>You can profile any of your page handlers (exposed methods) as follows:</para>
+            <example>
+                <title>Profiling example</title>
+                <programlisting><code>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()</code></programlisting>
+            </example>
+            <para>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.</para>
+            <para>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.</para>
+        </section>
+        <section>
+            <title>cherrypy.lib.autoreload</title>
+            <para>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>
+                    <title>The autoreload process</title>
+                    <mediaobject>
+                        <imageobject>
+                            <imagedata fileref="autoreload.gif" format="GIF" />
+                        </imageobject>
+                    </mediaobject>
+                </figure></para>
+        </section>
+    </section>
+    <section id="specialfunctions">
+        <title>Special functions and attributes</title>
+        <section>
+            <title>_cp_on_error</title>
+            <para>_cp_on_error is a function for handling unanticipated exceptions, whether raised by
+            CherryPy itself, or in user applications. The default simply responds as if
+            HTTPError(500) had been raised.</para>
+        </section>
+        <section>
+            <title>_cp_on_http_error</title>
+            <para>_cp_on_http_error handles HTTPError responses, setting cherrypy.response.status,
+            headers, and body.</para>
+        </section>
+        <section>
+            <title>_cp_filters</title>
+            <para>User defined filters are enabled using the class attribute _cp_filters. Any filter
+            instances placed in _cp_filters will be applied to all methods of the class.</para>
+        </section>
+        <section>
+            <title>_cp_log_access</title>
+            <para>Function to log HTTP requests into the access.log file.</para>
+        </section>
+        <section>
+            <title>_cp_log_message</title>
+            <para>Function to log errors into the error.log file. The <code>cherrypy.log</code>
+            function is syntactic sugar for this one.</para>
+        </section>
+    </section>
+    <section id="filters">
+        <title>Filter API</title>
+        <para>CherryPy provides a set of hooks which are called at specific places during the request
+        process. A filter should inherit from the BaseFilter class and implement the hooks it
+        requires to add extra code during the process. CherryPy will go through all the filters which
+        are on (buil-in and user defined) for that requested path and call all hooks that are
+        implemented by each filter.</para>
+        <section>
+            <title>on_start_resource</title>
+            <para>This hook is being called righ at the beginning of the request process. The only
+            work CherryPy has done when this hook is called is to parse the first line of the HTTP
+            request. This is needed so that filters have access to the object path translated from
+            the path specified in the HTTP request.</para>
+            <para>This hook is always called.</para>
+        </section>
+        <section>
+            <title>before_request_body</title>
+            <para>This hook is being called right after CherryPy has parse the HTTP request headers
+            but before it tries to parse the request body. If a filter which implements that hook
+            sets cherrypy.request.processRequestBody to False, CherryPy will not parse the request
+            body at all. This can be handy when you know your user agent returns the data in a form
+            that the default CherryPy request body parsing function cannot understand.</para>
+            <para>For example, assuming your user agent returns you a request body which is an XML
+            string unquoted, you may want a filter to parse that XML string and generates an XML DOM
+            instance. Then the filter could add that instance to the cherrypy.request.params which in
+            turns would be passed to your page handler like if it had actually been sent like that
+            through the HTTP request. Therefore your filter has turned the XML string into an XML DOM
+            instance transparently and makes your life easier. In that case you do not want CherryPy
+            to parse the request body. It could also be used to scan the request body before it is
+            being processed any further and decide to reject it if needed.</para>
+            <para>This hook is not called if an error occurs during the process before hand.</para>
+        </section>
+        <section>
+            <title>before_main</title>
+            <para>This hook is called right before your page handler (exposed callable) is being
+            called by CherryPy. It can be handy if considering HTTP request headers or body you may
+            want not to call the page handler at all, then you would have to set
+            cherrypy.request.executeMain to False.</para>
+            <para>This hook is not called if an error occurs during the process before hand.</para>
+        </section>
+        <section>
+            <title>before_finalize</title>
+            <para>This hook is called right after the page handler has been processed (depending on
+            the before_main hook behavior) and before CherryPy formats the final respone object. It
+            helps you for example to check for what could have been returned by your page handler and
+            change some headers of needed.</para>
+            <para>This hook is not called if an error occurs during the process before hand.</para>
+        </section>
+        <section>
+            <title>on_end_resource</title>
+            <para>This hook is called at the end of the process so that you can finely tweak your
+            HTTP response if needed (eg adding headers to the cherrypy.response.header_list). Note
+            that cherrypy.response.headers will not be processed any longer at that stage.</para>
+            <para>This hook is always called.</para>
+        </section>
+        <section>
+            <title>before_error_response</title>
+            <para>This hook is called when an error has occured during the request processing. It
+            allows you to called code before the _cp_on_error handler is being called as well as the
+            response finalizing stage.</para>
+        </section>
+        <section>
+            <title>after_error_response</title>
+            <para>This hook is called when an error has occured during the request processing. It
+            allows you to call code after the _cp_on_error handler is being called as well as the
+            response finalizing stage.</para>
+        </section>
+    </section>
+</section>