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

Changeset 637

Show
Ignore:
Timestamp:
09/13/05 17:03:33
Author:
mikerobi
Message:

minor change to the test system, all ticket:288 changes should be complete

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/mikerobi-experimental/CHANGELOG.txt

    r615 r637  
     12005-09-04: 
     2    * Generalized mechanism for handling HTTP errors 
     3    * raising a HTTPStatusError will automatically send an appropriate error page 
     4    * All errors in production mode will cause CP to respond with a http error 
     5 
    162005-08-17: 
    27    * The session filter has been simplified, the mechanism for creating multiple sessions has been removed. However .. (mikerobi) 
  • branches/mikerobi-experimental/cherrypy/_cperror.py

    r634 r637  
    174174 
    175175class HTTPError(Error): 
    176     """Exception raised when the client has made an error in its request.""" 
     176    """ Exception raised when the client has made an error in its request. 
     177        This exception will automatically set the response status and body. 
     178         
     179        A custom body can be pased to the init method in place of the standard error page. 
     180    """ 
    177181     
    178182    def __init__(self, status=500, body=_missing): 
     
    187191 
    188192        if body is _missing: 
     193            # because the init method is called before the exception is raised 
     194            # it is impossible to embed the traceback in the error page at this point. 
     195            # We use a generator so that the error page is generated at a later point ( 
     196            # after the exception is raised). 
    189197            cherrypy.response.body = self.pageGenerator() 
    190198        else: 
  • branches/mikerobi-experimental/cherrypy/test/helper.py

    r615 r637  
    3737import webtest 
    3838import types 
     39import re 
     40 
    3941for _x in dir(cherrypy): 
    4042    y = getattr(cherrypy, _x) 
     
    127129        else: 
    128130            webtest.WebCase.getPage(self, url, headers, method, body) 
     131  
     132    def assertErrorPage(self, errorCode, pattern = ''): 
     133        """ Compare the response body with a built in error page. 
     134            The function will optionally look for the regexp pattern,  
     135            within the exception embedded in the error page. 
     136        """ 
     137 
     138        from cherrypy._cputil import getErrorStatusAndPage 
     139        page = getErrorStatusAndPage(errorCode, '')[1] 
     140 
     141        # escape the question marks 
     142        page = page.replace('?', r'\?') 
     143         
     144        # re to find the traceback in the page 
     145        traceRe = re.compile('(<pre id="traceback">)(</pre>)') 
     146 
     147        # stick the pattern in the page so we can match everythign 
     148        # at once 
     149        page = traceRe.sub( '\g<1>.*%s.*\g<2>' % pattern, page) 
     150         
     151        # check if there is no exception 
     152        if pattern and traceRe.search(self.body): 
     153            msg = 'No match for %s in body' % `pattern` 
     154            self._handlewebError(msg) 
     155        else: 
     156            if not re.search(page, self.body, re.DOTALL): 
     157                msg = 'Error page does not match' 
     158                self._handlewebError(msg) 
    129159 
    130160CPTestLoader = webtest.ReloadingTestLoader() 
  • branches/mikerobi-experimental/cherrypy/test/webtest.py

    r634 r637  
    286286                msg = 'No match for %s in body' % `pattern` 
    287287            self._handlewebError(msg) 
    288      
    289     def assertErrorPage(self, errorCode, pattern = ''): 
    290         from cherrypy._cputil import getErrorStatusAndPage 
    291         page = getErrorStatusAndPage(errorCode, '')[1] 
    292  
    293         # escape the question marks 
    294         page = page.replace('?', r'\?') 
    295          
    296         # re to find the traceback in the page 
    297         traceRe = re.compile('(<pre id="traceback">)(</pre>)') 
    298  
    299         # stick the pattern in the page so we can match everythign 
    300         # at once 
    301         page = traceRe.sub( '\g<1>.*%s.*\g<2>' % pattern, page) 
    302          
    303         # check if there is no exception 
    304         if pattern and traceRe.search(self.body): 
    305             msg = 'No match for %s in body' % `pattern` 
    306             self._handlewebError(msg) 
    307         else: 
    308             if not re.search(page, self.body, re.DOTALL): 
    309                 msg = 'Error page does not match' 
    310                 self._handlewebError(msg) 
    311  
     288    
    312289 
    313290def cleanHeaders(headers, method, body, host, port): 
  • branches/mikerobi-experimental/docs/book/xml/adminreference.xml

    r325 r637  
    77   
    88  <xi:include href="installapplication.xml"/> 
     9  <xi:include href="configreference.xml"/> 
    910  <xi:include href="configureapplication.xml"/> 
    1011  <xi:include href="productionsetup.xml"/> 
  • branches/mikerobi-experimental/docs/book/xml/appdeveloperreference.xml

    r615 r637  
    1 <?xml version="1.0" encoding="utf-8"?> 
    2 <section xmlns:db="http://docbook.org/docbook-ng" xmlns:xi="http://www.w3.org/2001/XInclude" 
    3     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:id="appdeveloperreference"> 
    4     <title>Application developer reference</title> 
    5     <abstract>CherryPy tries to bring to Python developers a system that let them use their language 
    6         to develop web application as they would use it for any other type of environment. Therefore, 
    7         building a web application with CherryPy is very straightforward and does not require the 
    8         developer to change his/her habits, nor to learn many features before being able to pull out a 
    9         working application. This section will review the basic bricks offered by CherryPy to build an  
    10         application.</abstract> 
    11     <xi:include href="globaloverviewcherrypy.xml"/> 
    12     <xi:include href="configsystemoverview.xml"/> 
    13     <xi:include href="sessions.xml"/> 
    14     <xi:include href="templateindependant.xml"/> 
    15     <xi:include href="staticcontenthandling.xml"/> 
    16     <xi:include href="fileuploadbehavior.xml"/> 
     1<?xml version="1.0" encoding="UTF-8"?> 
     2<section xmlns:db="http://docbook.org/docbook-ng" 
     3         xmlns:xi="http://www.w3.org/2001/XInclude" 
     4         xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     5         xml:id="appdeveloperreference"> 
     6  <title>Application developer reference</title> 
     7  <abstract>CherryPy lets developers use Python to develop web applications, 
     8  just as they would use Python for any other type of application. Building a 
     9  web application with CherryPy is very straightforward and does not require 
     10  the developer to change habits, or learn many features, before being able to 
     11  produce a working application. This section will review the basic components 
     12  which CherryPy provides to build an application.</abstract> 
     13  <xi:include href="globaloverviewcherrypy.xml" /> 
     14  <xi:include href="configsystemoverview.xml" /> 
     15  <xi:include href="sessions.xml" /> 
     16  <xi:include href="templateindependant.xml" /> 
     17  <xi:include href="staticcontenthandling.xml" /> 
     18  <xi:include href="fileuploadbehavior.xml" /> 
    1719</section> 
  • branches/mikerobi-experimental/docs/book/xml/configsystemoverview.xml

    r615 r637  
    1 <?xml version="1.0" encoding="utf-8"?> 
    2 <section xmlns:db="http://docbook.org/docbook-ng" xmlns:xi="http://www.w3.org/2001/XInclude" 
    3     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:id="configsystemoverview"> 
    4     <title>Configuration system overview</title> 
    5     <para>The CherryPy configuration system specifies with a fine grain how each part of the 
    6         application should react. You will use it for two reason: </para> 
    7     <itemizedlist> 
    8         <listitem>Web server settings</listitem> 
    9         <listitem>Enabling filters per path</listitem> 
    10     </itemizedlist> 
    11     <para>You will be able to declare the configuration settings either from a file or from a Python 
    12         dictionnary.</para> 
    13     <para>First of all, let&apos;s see how a typical configuration file is defined.</para> 
    14     <example> 
    15         <title>Configuration file</title> 
    16         <programlisting linenumbering="numbered"> 
    17             #The configuration file called myconfigfile.conf 
     1<?xml version="1.0" encoding="UTF-8"?> 
     2<section xmlns:db="http://docbook.org/docbook-ng" 
     3         xmlns:xi="http://www.w3.org/2001/XInclude" 
     4         xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     5         xml:id="configsystemoverview"> 
     6  <title>Configuration system overview</title> 
     7  <para>The CherryPy configuration system provides fine-grained control over 
     8  how each part of the application should react. You will use it for two 
     9  reasons:</para> 
     10  <itemizedlist> 
     11    <listitem>Web server settings</listitem> 
     12    <listitem>Enabling filters per path</listitem> 
     13  </itemizedlist> 
     14  <para>You will be able to declare the configuration settings either from a 
     15  file or from a Python dictionary.</para> 
     16  <para>First of all, let's see how a typical configuration file is 
     17  defined.</para> 
     18  <example> 
     19    <title>Configuration file</title> 
     20    <programlisting linenumbering="numbered"> 
     21            # The configuration file called myconfigfile.conf 
    1822            [global] 
    1923            server.socketPort=8080 
     
    4145            cherrypy.config.update(file="myconfigfile.conf")  
    4246        </programlisting> 
    43     </example> 
    44     <para>The settings can also be defined using a python dictionnary instead of a file as follow :</para> 
    45     <example> 
    46         <title>Configuration dictionnary</title> 
    47         <programlisting linenumbering="numbered"> 
     47  </example> 
     48  <para>The settings can also be defined using a python dictionary instead of 
     49  a file as follows:</para> 
     50  <example> 
     51    <title>Configuration dictionary</title> 
     52    <programlisting linenumbering="numbered"> 
    4853      settings = {  
    49          &apos;global&apos;: { 
    50             &apos;server.socketPort&apos; : 8080, 
    51             &apos;server.socketHost&apos;: "", 
    52             &apos;server.socketFile&apos;: "", 
    53             &apos;server.socketQueueSize&apos;: 5, 
    54             &apos;server.protocolVersion&apos;: "HTTP/1.0", 
    55             &apos;server.logToScreen&apos;: True, 
    56             &apos;server.logFile&apos;: "", 
    57             &apos;server.reverseDNS&apos;: False, 
    58             &apos;server.threadPool&apos;: 10, 
    59             &apos;server.environment&apos;: "development" 
     54         'global': { 
     55            'server.socketPort' : 8080, 
     56            'server.socketHost': "", 
     57            'server.socketFile': "", 
     58            'server.socketQueueSize': 5, 
     59            'server.protocolVersion': "HTTP/1.0", 
     60            'server.logToScreen': True, 
     61            'server.logFile': "", 
     62            'server.reverseDNS': False, 
     63            'server.threadPool': 10, 
     64            'server.environment': "development" 
    6065         }, 
    61          &apos;/service/xmlrpc&apos; : { 
    62             &apos;xmlRpcFilter.on&apos;: True 
     66         '/service/xmlrpc' : { 
     67            'xmlRpcFilter.on': True 
    6368         }, 
    64          &apos;/admin&apos;: { 
    65             &apos;sessionAuthenticateFilter.on&apos; :True 
     69         '/admin': { 
     70            'sessionAuthenticateFilter.on' :True 
    6671         }, 
    67          &apos;/css/default.css&apos;: { 
    68             &apos;staticFilter.on&apos;: True, 
    69             &apos;staticFilter.file&apos;: "data/css/default.css" 
     72         '/css/default.css': { 
     73            'staticFilter.on': True, 
     74            'staticFilter.file': "data/css/default.css" 
    7075         } 
    7176      } 
    7277      cherrypy.config.update(settings) 
    7378        </programlisting> 
    74     </example> 
    75     <para>Each section of the configuration is a path that can be mapped to a published object 
    76         of the tree handled by CherryPy. Therefore when the server receives a request to 
    77             <code>/css/default.css</code> the static filter will be called and the server will 
    78         actually return the physical file name <filename>data/css/default.css</filename>. </para> 
    79     <para>Since the path <code>/service/xmlrpc</code> has the XML-RPC filter enabled, all the 
    80         exposed methods of the object <code>cherrypy.root.service.xmlrpc</code> will be treated as 
    81         XML-RPC methods.</para> 
    82     <para>The root entry, defined as <code>global</code>, is also responsible for defining the 
    83         server settings such as the port, the protocol version to use by default, the number of 
    84         threads to start with the server, etc.</para> 
    85     <para>The configuration file requires that all the value are Python values. Strings must be 
    86         quoted, boolean are set to True or False, etc.</para> 
    87     <para>The <code>server.environment</code> entry controls how CherryPy should run. Three values 
    88         are legal :</para> 
    89     <itemizedlist> 
    90         <listitem>development <itemizedlist> 
    91                 <listitem>logDebugInfoFilter is enabled by default</listitem> 
    92                 <listitem> the default _cpOnError displays tracebacks in the browser if errors occur 
    93                     but still returns a "200" status code</listitem> 
    94                 <listitem>autoreload is enabled by default</listitem> 
    95             </itemizedlist> 
     79  </example> 
     80  <para>Each section of the configuration refers to a URL path; each path is 
     81  mapped to a published object of the tree handled by CherryPy. Therefore when 
     82  the server receives a request for <code>/css/default.css</code>, the static 
     83  filter will be called and the server will actually return the physical file 
     84  name <filename>data/css/default.css</filename>.</para> 
     85  <para>Since the path <code>/service/xmlrpc</code> has the XML-RPC filter 
     86  enabled, all the exposed methods of the object 
     87  <code>cherrypy.root.service.xmlrpc</code> will be treated as XML-RPC 
     88  methods.</para> 
     89  <para>The root entry, defined as <code>global</code>, is also responsible 
     90  for defining the server settings such as the port, the protocol version to 
     91  use by default, the number of threads to start with the server, etc.</para> 
     92  <para>All values in the configuration file must be valid Python values. 
     93  Strings must be quoted, booleans must be True or False, etc.</para> 
     94  <para>The <code>server.environment</code> entry controls how CherryPy should 
     95  run. Three values are legal:</para> 
     96  <itemizedlist> 
     97    <listitem>development <itemizedlist> 
     98        <listitem>logDebugInfoFilter is enabled by default</listitem> 
     99        <listitem>the default _cpOnError displays tracebacks in the browser if 
     100        errors occur</listitem> 
     101        <listitem>autoreload is enabled by default</listitem> 
     102      </itemizedlist></listitem> 
     103    <listitem>production <itemizedlist> 
     104        <listitem>logDebugInfoFilter is disabled by default</listitem> 
     105        <listitem> 
     106          <para>tracebacks are logged, but are not displayed in the 
     107          browser</para> 
    96108        </listitem> 
    97         <listitem>production <itemizedlist> 
    98                 <listitem>logDebugInfoFilter is disabled by default</listitem> 
    99                 <listitem>the default _cpOnError returns "304" or "500" status codes if errors 
    100                 occur</listitem> 
    101             </itemizedlist> 
    102         </listitem> 
    103         <listitem>staging (same as production for the moment)</listitem> 
    104     </itemizedlist> 
     109        <listitem>autoreload is disabled by default</listitem> 
     110      </itemizedlist></listitem> 
     111    <listitem>staging (same as production for the moment)</listitem> 
     112  </itemizedlist> 
    105113</section> 
  • branches/mikerobi-experimental/docs/book/xml/fileuploadbehavior.xml

    r615 r637  
    1 <?xml version="1.0" encoding="utf-8"?> 
    2 <section xmlns:db="http://docbook.org/docbook-ng" xmlns:xi="http://www.w3.org/2001/XInclude" 
    3     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:id="globaloverviewcherrypy"> 
    4     <title>File upload</title> 
    5     <para>Before version 2.1, CherryPy was handling file uploads as follows: it was reading the entire file in memory, store it in a string and pass it to the method.  
    6         This works well for small files but not so well for big files.</para> 
    7          
    8         <para>CherryPy 2.1 uses the python <code>cgi</code> module to parse the POST data.  
    9             When a file is being uploaded, this modules stores it in a temp file and returns a <code>FieldStorage</code> instance which contains information about this file.  
    10             CherryPy then passes this <code>FieldStorage</code> instance to the method, this instance has the following attributes:</para> 
    11          
    12     <itemizedlist> 
    13         <listitem><code>file</code>: the file(-like) object from which you can read the data</listitem> 
    14         <listitem><code>filename</code>: the client-side filename</listitem> 
    15         <listitem><code>type</code>: the content-type of the file </listitem> 
    16     </itemizedlist> 
    17     </section> 
     1<?xml version="1.0" encoding="UTF-8"?> 
     2<section xmlns:db="http://docbook.org/docbook-ng" 
     3         xmlns:xi="http://www.w3.org/2001/XInclude" 
     4         xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     5         xml:id="globaloverviewcherrypy"> 
     6  <title>File upload</title> 
     7  <para>Before version 2.1, CherryPy handled file uploads by reading the 
     8  entire file into memory, storing it in a string, and passing it to the page 
     9  handler. This worked well for small files, but not so well for large 
     10  files.</para> 
     11  <para>CherryPy 2.1 uses the python <code>cgi</code> module to parse the POST 
     12  data. When a file is being uploaded, the <code>cgi</code> module stores it 
     13  in a temp file and returns a <code>FieldStorage</code> instance which 
     14  contains information about this file. CherryPy then passes this 
     15  <code>FieldStorage</code> instance to the method. The 
     16  <code>FieldStorage</code> instance has the following attributes:</para> 
     17  <itemizedlist> 
     18    <listitem><code>file</code>: the file(-like) object from which you can 
     19    read the data</listitem> 
     20    <listitem><code>filename</code>: the client-side filename</listitem> 
     21    <listitem><code>type</code>: the content-type of the file</listitem> 
     22  </itemizedlist> 
     23</section> 
  • branches/mikerobi-experimental/docs/book/xml/globaloverviewcherrypy.xml

    r615 r637  
    1 <?xml version="1.0" encoding="utf-8"?> 
    2 <section xmlns:db="http://docbook.org/docbook-ng" xmlns:xi="http://www.w3.org/2001/XInclude" 
    3   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:id="globaloverviewcherrypy"> 
     1<?xml version="1.0" encoding="UTF-8"?> 
     2<section xmlns:db="http://docbook.org/docbook-ng" 
     3         xmlns:xi="http://www.w3.org/2001/XInclude" 
     4         xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     5         xml:id="globaloverviewcherrypy"> 
    46  <title>Filters</title> 
    5   <para>Filters are one of the most important features of CherryPy. A filter is a class defining a 
    6     set of function that will be called by the core at specific point of a request processing. The 
    7     very nature of filters are to let the developer write code that will be called at a low level - 
    8     the HTTP request/response level - and therefore should only be used in that context.</para> 
    9   <para>CherryPy comes with a set of filters which are turned off by default. To enable them, you 
    10     must use the configuration system as follow :</para> 
     7  <para>Filters are one of the most important features of CherryPy. The 
     8  CherryPy core can call user-defined functions at specific points during 
     9  request processing; a filter is a class which defines those functions. 
     10  Filters are designed to be called at a low level—the HTTP request/response 
     11  level—and therefore should only be used in that context.</para> 
     12  <para>CherryPy comes with a set of built-in filters, but they're turned off 
     13  by default. To enable them, you must use the configuration system as 
     14  follows:</para> 
    1115  <itemizedlist> 
    12     <listitem>First you must decide at which level of the cherrypy tree of published objects you 
    13       need the filter to act on. The filter will then act on that level and all its sub-levels in 
    14       the tree. Remember that the tree is accessed as a path and then mapped internally by the core 
    15       to match the correct exposed object.</listitem> 
    16     <listitem>Second in the config file you must turn the filter on like this : <code>filterName.on 
    17         = True</code></listitem> 
     16    <listitem>First you must decide where to enable the filter. CherryPy 
     17    maintains a tree of published objects; you must decide which branch should 
     18    use the filter. The filter will then apply to that branch and all its 
     19    children in the tree. Remember that the tree is accessed as a path and 
     20    then mapped internally by the core to match the correct exposed 
     21    object.</listitem> 
     22    <listitem>Second in the config file you must turn the filter on like this 
     23    : <code>filterName.on = True</code></listitem> 
    1824  </itemizedlist> 
    1925  <example> 
     
    2632      </programlisting> 
    2733  </example> 
    28   <para> On the first line we define that when the path <code>/entries/view</code> is called, or one 
    29     of its sub-paths, the tidy filter will be used by the core. On the two last lines we also define 
    30     some parameters used by the filter. </para> 
    31   <para>CherryPy lets you write your own filters as we will see in the developer reference chapter. 
    32     Nonetheless the way to use them is different from the default filters since you do not declare 
    33     them within the configuration file but from the source code itself using the 
    34     <code>_cpFilterList</code> list as a class member of the object that will use the filter.</para> 
     34  <para>On the first line we define that the tidy filter will be used by the 
     35  core whenever the path <code>/entries/view</code> (or one of its sub-paths) 
     36  is called. On the two last lines we also define some parameters used by the 
     37  filter.</para> 
     38  <para>CherryPy lets you write your own filters as we will see in the 
     39  developer reference chapter. However, the way to use them is different from 
     40  the default filters. You do not declare custom filters within the 
     41  configuration file; instead, use the <code>_cpFilterList</code> attribute in 
     42  your source code:</para> 
    3543  <example> 
    3644    <title>Using a non default filter</title> 
     
    5260      </programlisting> 
    5361  </example> 
    54   <para>As all objects below <code>cherrypy.root.entries</code> will inherit the filter, there is no 
    55     need to re-specify it in each <code>_cpFilterList</code> underneath.</para> 
    56   <para>Keep in mind that the user defined filters are called in the order you add them to the 
    57   list.</para> 
     62  <para>As all objects below <code>cherrypy.root.entries</code> will inherit 
     63  the filter, there is no need to re-specify it in each 
     64  <code>_cpFilterList</code> underneath.</para> 
     65  <para>Keep in mind that the user-defined filters are called in the order you 
     66  add them to the list.</para> 
    5867</section> 
  • branches/mikerobi-experimental/docs/book/xml/sessions.xml

    r615 r637  
    1 <?xml version="1.0" encoding="utf-8"?> 
    2 <section xmlns:db="http://docbook.org/docbook-ng" xmlns:xi="http://www.w3.org/2001/XInclude" 
    3   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:id="sessions"> 
    4     <title>Session Management</title> 
    5     <abstract> 
    6         <para>CherryPy 2.1 includes a powerful sessions system provided via a new <literal>sessionFilter</literal>. </para> 
    7     </abstract> 
    8     <section id="usingsessions"> 
    9         <title>Using Sessions</title> 
    10         <para>First you need to enable the session filter through the configuration system, by setting <option>sessionFilter.on</option> to <literal>True</literal>. This gives you a variable called <literal>cherrypy.session</literal>, which is a dictionary-like object where you can read/store your session data. This dictionnary always has a special key called <literal>_id</literal> which contains the session id.</para> 
    11         <para>Here is a sample code showing how to implement a simple counter using sessions:</para> 
    12         <example> 
    13             <programlisting> 
     1<?xml version="1.0" encoding="UTF-8"?> 
     2<section xmlns:db="http://docbook.org/docbook-ng" 
     3         xmlns:xi="http://www.w3.org/2001/XInclude" 
     4         xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:id="sessions"> 
     5  <title>Session Management</title> 
     6  <abstract> 
     7    <para>CherryPy 2.1 includes a powerful sessions system provided via a new 
     8    <literal>sessionFilter</literal>.</para> 
     9  </abstract> 
     10  <section id="usingsessions"> 
     11    <title>Using Sessions</title> 
     12    <para>First you need to enable the session filter through the 
     13    configuration system, by setting <option>sessionFilter.on</option> to 
     14    <literal>True</literal>. This gives you a variable called 
     15    <literal>cherrypy.session</literal>, which is a dictionary-like object 
     16    where you can read/store your session data. This dictionary always has a 
     17    special key called <literal>_id</literal> which contains the session 
     18    id.</para> 
     19    <para>Here is sample code showing how to implement a simple counter using 
     20    sessions:</para> 
     21    <example> 
     22      <programlisting> 
    1423            import cherrypy 
    1524            class Root: 
     
    2332            cherrypy.server.start() 
    2433            </programlisting> 
    25         </example> 
    26     </section> 
    27     <section> 
    28         <title>Configuring sessions</title> 
    29         <para> The following configuration options are available for "sessionFilter": </para> 
    30         <itemizedlist> 
    31             <listitem> 
    32                 <para><option>sessionFilter.on</option>: 
    33                 <literal>True</literal> or <literal>False</literal> (default): enable/disable sessions</para> 
    34             </listitem> 
    35             <listitem> 
    36                 <para><option>sessionFilter.storageType</option>: 
    37                 Specify which storage type should be used for storing session data on the server. Built-in types are <literal>Ram</literal> (default), <literal>File</literal> and <literal>PostgreSQL</literal> (see <xref linkend="backends"/> for more info)</para> 
    38             </listitem> 
    39             <listitem> 
    40                 <para><option>sessionFilter.timeout</option>: 
    41                 The number of minutes of inactivity before an individual session can be removed. It can be a float (ex: 0.5 for 30 seconds). Defaults to 60.</para> 
    42             </listitem> 
    43             <listitem> 
    44                 <para><option>sessionFilter.cleanUpDelay</option>: 
    45                 Once in a while the server cleans up old/expired sessions. This config option specifies how often this clean up process should happe. The delay is in minutes. Defaults to 5.</para> 
    46             </listitem> 
    47             <listitem> 
    48                 <para><option>sessionFilter.cookieName</option>: 
    49                 The name of the cookie that CherryPy will use to store the session ID. Defaults to <literal>sessionID</literal>.</para> 
    50             </listitem> 
    51             <listitem> 
    52                 <para><option>sessionFilter.getDB</option>: 
    53                 See the <option>PostgreSQL</option> backend from <xref linkend="backends"/>.</para> 
    54             </listitem> 
    55             <listitem> 
    56                 <para><option>sessionFilter.deadlockTimeout</option>: 
    57                 See <xref linkend="concurrent"/>.</para> 
    58             </listitem> 
    59             <listitem> 
    60                 <para><option>sessionFilter.onCreateSession</option>: 
    61                 See <xref linkend="callbacks"/>.</para> 
    62             </listitem> 
    63             <listitem> 
    64                 <para><option>sessionFilter.onDeleteSession</option>: 
    65                 See <xref linkend="callbacks"/>.</para> 
    66             </listitem> 
    67             <listitem> 
    68                 <para><option>sessionFilter.storageClass</option>: 
    69                 See <xref linkend="custombackend"/>.</para> 
    70             </listitem> 
    71         </itemizedlist> 
    72     </section> 
    73  
    74     <section id="backends"> 
    75         <title>Choosing the backend</title> 
    76         <para>CherryPy comes with multiple build-in backends for storing session data on the server side. They are:</para> 
    77  
    78         <itemizedlist> 
    79             <listitem> 
    80                 <para><option>Ram</option>: 
    81                 All data is stored in RAM; this is the fastest storage, but it means that the data will be lost if you restart the server; and it also means that it won't scale to multiple processes/machines</para> 
    82             </listitem> 
    83             <listitem> 
    84                 <para><option>File</option>: 
    85                 All data is stored on disk; this is a bit slower than Ram storage, but the data will persist if you restart the server server; it also means that data can also be shared amongst multiple CherryPy processes (either on the same machine, or on multiple machines if all machines have access to the same disk ... through something like NFS for instance)</para> 
    86             </listitem> 
    87             <listitem> 
    88                 <para><option>PostgreSQL</option>: 
    89                 This backend is included with CherryPy to show how easy it is to implement your own custom backend for the session system. All data is stored in a PostgreSQL database; storing your data in a database is the recommend setup for production if you have a very high traffic website and you need to scale your site accross multiple machines. To use this backend you'll need to create the following table in your PostgreSQL database: 
    90                 <screen> 
     34    </example> 
     35  </section> 
     36  <section> 
     37    <title>Configuring sessions</title> 
     38    <para>The following configuration options are available for 
     39    "sessionFilter":</para> 
     40    <itemizedlist> 
     41      <listitem> 
     42        <para><option>sessionFilter.on</option>: <literal>True</literal> or 
     43        <literal>False</literal> (default): enable/disable sessions</para> 
     44      </listitem> 
     45      <listitem> 
     46        <para><option>sessionFilter.storageType</option>: Specify which 
     47        storage type should be used for storing session data on the server. 
     48        Built-in types are <literal>Ram</literal> (default), 
     49        <literal>File</literal> and <literal>PostgreSQL</literal> (see <xref 
     50        linkend="backends" /> for more info)</para> 
     51      </listitem> 
     52      <listitem> 
     53        <para><option>sessionFilter.timeout</option>: The number of minutes of 
     54        inactivity before an individual session can be removed. It can be a 
     55        float (ex: 0.5 for 30 seconds). Defaults to 60.</para> 
     56      </listitem> 
     57      <listitem> 
     58        <para><option>sessionFilter.cleanUpDelay</option>: Once in a while the 
     59        server cleans up old/expired sessions. This config option specifies 
     60        how often this clean up process should happen. The delay is in 
     61        minutes. Defaults to 5.</para> 
     62      </listitem> 
     63      <listitem> 
     64        <para><option>sessionFilter.cookieName</option>: The name of the 
     65        cookie that CherryPy will use to store the session ID. Defaults to 
     66        <literal>sessionID</literal>.</para> 
     67      </listitem> 
     68      <listitem> 
     69        <para><option>sessionFilter.getDB</option>: See the 
     70        <option>PostgreSQL</option> backend from <xref 
     71        linkend="backends" />.</para> 
     72      </listitem> 
     73      <listitem> 
     74        <para><option>sessionFilter.deadlockTimeout</option>: See <xref 
     75        linkend="concurrent" />.</para> 
     76      </listitem> 
     77      <listitem> 
     78        <para><option>sessionFilter.onCreateSession</option>: See <xref 
     79        linkend="callbacks" />.</para> 
     80      </listitem> 
     81      <listitem> 
     82        <para><option>sessionFilter.onDeleteSession</option>: See <xref 
     83        linkend="callbacks" />.</para> 
     84      </listitem> 
     85      <listitem> 
     86        <para><option>sessionFilter.storageClass</option>: See <xref 
     87        linkend="custombackend" />.</para> 
     88      </listitem> 
     89    </itemizedlist> 
     90  </section> 
     91  <section id="backends"> 
     92    <title>Choosing the backend</title> 
     93    <para>CherryPy comes with multiple build-in backends for storing session 
     94    data on the server side. They are:</para> 
     95    <itemizedlist> 
     96      <listitem> 
     97        <para><option>Ram</option>: All data is stored in RAM; this is the 
     98        fastest storage, but it means that the data will be lost if you 
     99        restart the server; and it also means that it won't scale to multiple 
     100        processes/machines</para> 
     101      </listitem> 
     102      <listitem> 
     103        <para><option>File</option>: All data is stored on disk; this is a bit 
     104        slower than Ram storage, but the data will persist if you restart the 
     105        server. It also means that data can be shared amongst multiple 
     106        CherryPy processes, either on the same machine, or on multiple 
     107        machines if all machines have access to the same disk (for example, 
     108        via NFS).</para> 
     109      </listitem> 
     110      <listitem><para><option>PostgreSQL</option>: This backend is included 
     111      with CherryPy to show how easy it is to implement your own custom 
     112      backend for the session system. All data is stored in a PostgreSQL 
     113      database; storing your data in a database is the recommend setup for 
     114      production if you have a very high traffic website and you need to scale 
     115      your site across multiple machines. To use this backend, you'll need to 
     116      create the following table in your PostgreSQL database: <screen> 
    91117                create table session ( 
    92118                    id varchar(40), 
     
    94120                    expiration_time timestamp 
    95121                ) 
    96                 </screen> 
    97                 </para> 
    98                 You also need to programmatically set the <literal>sessionFilter.getDB</literal> config option to a function that returns a DB connection. 
    99             </listitem> 
    100         </itemizedlist> 
    101     </section> 
    102  
    103     <section id="custombackend"> 
    104         <title>Writing your own custom backend</title> 
    105         <para>By default, CherryPy comes with 3 built-in backends, but if you have specific needs, it is very easy to implement your own custom backend (for instance, another database, or an XML-RPC server, ...). To do so, all you have to do is write a class that implements the following methods: 
    106             <screen> 
     122                </screen> </para> You also need to programmatically set the 
     123      <literal>sessionFilter.getDB</literal> config option to a function that 
     124      returns a DB connection.</listitem> 
     125    </itemizedlist> 
     126  </section> 
     127  <section id="custombackend"> 
     128    <title>Writing your own custom backend</title> 
     129    <para>By default, CherryPy comes with 3 built-in backends, but if you have 
     130    specific needs, it is very easy to implement your own custom backend (for 
     131    instance, another database, or an XML-RPC server, ...). To do so, all you 
     132    have to do is write a class that implements the following methods: 
     133    <screen> 
    107134            class MyCustomBackend: 
    108135                def save(self, id, data, expirationTime): 
     
    115142                    """ Delete expired session data from storage and call 
    116143                        'onDeleteSession' for each deleted session id """ 
    117             </screen> 
    118             Note that if you want to use <option>explicit</option> locking (see <xref linkend="concurrent"/>), you also have to implement two extra methods: <literal>acquireLock</literal> and <literal>releaseLock</literal>. 
    119         </para> 
    120  
    121         <para>Once you have written this class, you have to programmatically set the <literal>sessionFilter.storageClass</literal> config option to this class.</para> 
    122  
    123         <para>If you need help in writing your own custom backend it is a good idea to look at how the current ones (ram, file and postgresql) are implemented. They are implemented in the file <filename>cherrypy/lib/filter/sessionfilter.py</filename></para> 
    124     </section> 
    125  
    126     <section id="concurrent"> 
    127         <title>Handling concurrent requests for the same session data</title> 
    128         <para>It is normally quite rare to have to simultaneous requests with the same session ID. It means that a same browser is making 2 requests to your server at the same time (to dynamic pages ... static pages don't have sessions). However, this case can happen (if you're using frames for instance), and it will happen more and more often as more and more people start using Ajax.</para> 
    129         <para>In that case, we need to make sure that access to the session data is serialized. This way threads can't both modify the data at the same time and leave it in an inconsistent state.</para> 
    130         <para>By default, CherryPy will serialize access to the session data, so if a browser makes a second request while a first request is still being handled by the server, the second request will block while the first request is accessing the data. As soon as the first request is finished then the second request will be able to access it.</para> 
    131         <para>This means that the second request will block until the first request is finished. If you're using the <option>ram</option> backend, you can manually shorten the window where the second request will block. This is achieved by having the first request explicitely tell CherryPy when it starts using the session data and when it is finished with it. In order to do so, you have to call <literal>cherrypy.session.acquireLock</literal> and <literal>cherrypy.session.releaseLock</literal>. You also have to set the <literal>sessionFilter.locking</literal> config option to <option>explicit</option>.</para> 
    132         <para>Note that this technique only works with the <option>ram</option> backend. For other backends like <option>file</option> or <option>postgresql</option>, it is not safe to release the session before the request is finished, because the session data will only be saved at the end of the request anyway. So it would be bad if some other thread started accessing the data between the time when it is released and the time when it is saved. 
    133         </para> 
    134     </section> 
    135  
    136     <section id="callbacks"> 
    137         <title>Being notified when sessions are created/deleted</title> 
    138         <para>It is possible to configure the <literal>sessionFilter</literal> so that it calls some special callback functions from your code when sessions are being created/deleted. To do so you have to set the <literal>sessionFilter.onCreateSession</literal> and <literal>sessionFilter.onDeleteSession</literal> config options. When a session is created/deleted, CherryPy will call these functions and pass them the session data.</para> 
    139     </section> 
     144            </screen> Note that if you want to use <option>explicit</option> 
     145    locking (see <xref linkend="concurrent" />), you also have to implement 
     146    two extra methods: <literal>acquireLock</literal> and 
     147    <literal>releaseLock</literal>.</para> 
     148    <para>Once you have written this class, you have to programmatically set 
     149    the <literal>sessionFilter.storageClass</literal> config option to this 
     150    class.</para> 
     151    <para>If you need help in writing your own custom backend it is a good 
     152    idea to look at how the current ones (ram, file and postgresql) are 
     153    implemented. They are implemented in the file 
     154    <filename>cherrypy/lib/filter/sessionfilter.py</filename></para> 
     155  </section> 
     156  <section id="concurrent"> 
     157    <title>Handling concurrent requests for the same session data</title> 
     158    <para>It is normally quite rare to have two simultaneous requests with the 
     159    same session ID. It means that a same browser is making 2 requests to your 
     160    server at the same time (to dynamic pages ... static data like images 
     161    don't have sessions). However, this case can happen (if you're using 
     162    frames for instance), and it will happen more and more often as more and 
     163    more people start using Ajax.</para> 
     164    <para>In that case, we need to make sure that access to the session data 
     165    is serialized. This way, threads can't both modify the data at the same 
     166    time and leave it in an inconsistent state.</para> 
     167    <para>By default, CherryPy will serialize access to the session data, so 
     168    if a browser makes a second request while a first request is still being 
     169    handled by the server, the second request will block while the first 
     170    request is accessing the data. As soon as the first request is finished 
     171    then the second request will be able to access it.</para> 
     172    <para>This means that the second request will block until the first 
     173    request is finished. If you're using the <option>ram</option> backend, you 
     174    can manually shorten the window where the second request will block. This 
     175    is achieved by having the first request explicitly tell CherryPy when it 
     176    starts using the session data and when it is finished with it. In order to 
     177    do so, you have to call <literal>cherrypy.session.acquireLock</literal> 
     178    and <literal>cherrypy.session.releaseLock</literal>. You also have to set 
     179    the <literal>sessionFilter.locking</literal> config option to 
     180    <option>explicit</option>.</para> 
     181    <para>Note that this technique only works with the <option>ram</option> 
     182    backend. For other backends like <option>file</option> or 
     183    <option>postgresql</option>, it is not safe to release the session before 
     184    the request is finished, because the session data will only be saved at 
     185    the end of the request anyway. So it would be bad if some other thread 
     186    started accessing the data between the time when it is released and the 
     187    time when it is saved.</para> 
     188  </section> 
     189  <section id="callbacks"> 
     190    <title>Being notified when sessions are created/deleted</title> 
     191    <para>It is possible to configure the <literal>sessionFilter</literal> so 
     192    that it calls some special callback functions from your code when sessions 
     193    are being created/deleted. To do so you have to set the 
     194    <literal>sessionFilter.onCreateSession</literal> and 
     195    <literal>sessionFilter.onDeleteSession</literal> config options. When a 
     196    session is created/deleted, CherryPy will call these functions and pass 
     197    them the session data.</para> 
     198  </section> 
    140199</section> 
    141  
  • branches/mikerobi-experimental/docs/book/xml/staticcontenthandling.xml

    r615 r637  
    1 <?xml version="1.0" encoding="utf-8"?> 
    2 <section xmlns:db="http://docbook.org/docbook-ng" xmlns:xi="http://www.w3.org/2001/XInclude" 
    3     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:id="globaloverviewcherrypy"> 
    4     <title>Static content handling</title> 
    5     <para>Static content is now handled by a filter called "staticFilter" that can easily be enabled and configured in your config file.  
    6         For instance, if you wanted to serve <code>/style.css</code> from <filename>/home/site/style.css</filename> and <code>/static/*</code> 
    7         from <filename>/home/site/static/*</filename>, you can use the following configuration: 
    8         </para> 
    9          
    10     <example> 
    11         <title>Static filter configuration</title> 
    12         <programlisting> 
     1<?xml version="1.0" encoding="UTF-8"?> 
     2<section xmlns:db="http://docbook.org/docbook-ng" 
     3         xmlns:xi="http://www.w3.org/2001/XInclude" 
     4         xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     5         xml:id="globaloverviewcherrypy"> 
     6  <title>Static content handling</title> 
     7  <para>Static content is now handled by a filter called "staticFilter" that 
     8  can easily be enabled and configured in your config file. For instance, if 
     9  you wanted to serve <code>/style.css</code> from 
     10  <filename>/home/site/style.css</filename> and <code>/static/*</code> from 
     11  <filename>/home/site/static/*</filename>, you can use the following 
     12  configuration:</para> 
     13  <example> 
     14    <title>Static filter configuration</title> 
     15    <programlisting> 
    1316            [global] 
    1417            staticFilter.root = "/home/site" 
     
    2225            staticFilter.dir = "static" 
    2326        </programlisting> 
    24     </example> 
    25     <para>The <code>staticFilter.root</code> entry is not required; if you omit it, it defaults to the directory of your <code>cherrypy.root</code> class. </para> 
    26    </section> 
     27  </example> 
     28  <para>The <code>staticFilter.root</code> entry can be either absolute or 
     29  relative. If absolute, static content is sought within that absolute path. 
     30  Since CherryPy cannot guess where your application root is located, relative 
     31  paths are assumed to be relative to the directory where your 
     32  <code>cherrypy.root</code> class is defined (if you do not provide a root, 
     33  it defaults to "", and therefore to the directory of your 
     34  <code>cherrypy.root</code> class).</para> 
     35  <para>As an application developer, the design of your application affects 
     36  whether you choose to use absolute or relative paths. If you are creating a 
     37  one-off application that will only be deployed once, you might as well use 
     38  absolute paths. But you can make multiple deployments easier by using 
     39  relative paths, letting CherryPy calculate the absolute path each time for 
     40  you. Absolute paths, however, give deployers the ability to place static 
     41  content on read-only filesystems, or on faster disks.</para> 
     42</section> 
  • branches/mikerobi-experimental/docs/book/xml/templateindependant.xml

    r615 r637  
    1 <?xml version="1.0" encoding="utf-8"?> 
    2 <section xmlns:db="http://docbook.org/docbook-ng" xmlns:xi="http://www.w3.org/2001/XInclude" 
    3     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:id="templateindependant"> 
    4     <title>Templating language independant</title> 
    5     <para>CherryPy is a low level framework to build web application and thus does not  
    6     offer high level features such as an integrated templating system. This is quite a different 
    7         point of view from the other web frameworks already existing.</para> 
    8     <para>The great point is that CherryPy does not force you to use a specific tamplating language, 
    9        instead it allows you to plug your favourite one the way you need. 
    10     </para> 
    11     <para>CherryPy has been reported to be working with all the main templating systems:</para> 
    12     <itemizedlist> 
    13         <listitem> 
    14&