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

Changeset 202

Show
Ignore:
Timestamp:
05/22/05 14:10:52
Author:
rdelon
Message:

Another big change: Changed config system; Added default filters; See http://www.cherrypy.org/wiki/WhatsNewIn21 ; Added tests for filters

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/_cpconfig.py

    r199 r202  
    3131# Default config options 
    3232configMap = { 
    33         'server': { 
    34             'protocolVersion': 'HTTP/1.0', 
    35             'logToScreen': True, 
    36             'logFile': '', 
    37             'socketHost': '', 
    38             'socketPort': 8080, 
    39             'socketFile': '', 
    40             'reverseDNS': False, 
    41             'socketQueueSize': 5, 
    42             'protocolVersion': 'HTTP/1.0', 
    43             'threadPool': 0, 
    44             'environment': 'dev'}, 
    45         'session': { 
    46             'storageType': 'ram', 
    47             'timeout': 60, 
    48             'cleanUpDelay': 60, 
    49             'cookieName': 'CherryPySession', 
    50             'storageFileDir': '', 
     33        '/': { 
     34            'server.socketPort': 8080, 
     35            'server.socketHost': '', 
     36            'server.socketFile': '', 
     37            'server.socketQueueSize': 5, 
     38 
     39            'server.env': 'dev', 
     40            'server.protocolVersion': 'HTTP/1.0', 
     41            'server.logToScreen': True, 
     42            'server.logFile': '', 
     43            'server.reverseDNS': False, 
     44            'server.threadPool': 0, 
     45            'server.environment': 'prod', 
     46 
     47            'session.storageType': 'ram', 
     48            'session.timeout': 60, 
     49            'session.cleanUpDelay': 60, 
     50            'session.cookieName': 'CherryPySession', 
     51            'session.storageFileDir': '', 
     52 
     53            'staticContent': {} 
    5154        }, 
    52         'staticContent': {} 
    5355    } 
    5456 
     
    6466        _load(file) 
    6567 
    66 def get(section, attrName = None, defaultValue = None): 
    67     if attrName: 
    68         return configMap.get(section, {}).get(attrName, defaultValue) 
     68def _getSlashSections(): 
     69    """ Return all config sections from configMap 
     70        that start with a slash and return them sorted by length 
     71        (longest first) 
     72    """ 
     73    # TODO: the result could be cached and recomputed when 
     74    #   config.update() is called 
     75    sectionList = [section for section in configMap.keys() 
     76        if (section[0] == '/' or section.startswith('http://') or 
     77            section.startswith('https://'))] 
     78    sectionList.sort(_sortOnLength) 
     79    return sectionList 
     80 
     81def _sortOnLength(a, b): 
     82    l1, l2 = len(a), len(b) 
     83    if l1 == l2: 
     84        return 0 
     85    elif l1 < l2: 
     86        return 1 
    6987    else: 
    70         return configMap.get(section, defaultValue) 
    71  
    72 def getForPath(attrNam, defaultValue = None): 
    73     raise "TODO" 
     88        return -1 
     89 
     90def _getFor(path, key, defaultValue = None, returnSection = False): 
     91    for section in _getSlashSections(): 
     92        if path.startswith(section): 
     93            res = configMap[section].get(key, '#NULL#') 
     94            if res != '#NULL#': 
     95                if returnSection: 
     96                    return section 
     97                return res 
     98    return defaultValue 
     99 
     100def _cast(type, value): 
     101    if type is None: 
     102        return value 
     103    if type == 'int': 
     104        return int(value) 
     105    elif type == 'float': 
     106        return float(value) 
     107    elif type == 'bool': 
     108        if isinstance(value, basestring): 
     109            value = value.lower() 
     110        if (not value) or (value in ('false', 'off', '0')): 
     111            return False 
     112        return True 
     113    elif type == 'list': 
     114        if isinstance(value, list): 
     115            return value 
     116        assert (not value) or ( 
     117            value[0] in ('(', '[') and value[-1] in (')', ']')) 
     118        return eval(value) # Convert value to list 
     119 
     120def get(key, defaultValue = None, cast = None, returnSection = False): 
     121    # First try the whole browserUrl 
     122    try: 
     123        path = cpg.request.browserUrl 
     124    except: 
     125        # At startup, we don't have a path yet 
     126        path = '/' 
     127    res = _getFor(path, key, '#NULL#', returnSection) 
     128    if res != '#NULL#': 
     129        return _cast(cast, res) 
     130    # Then try just path 
     131    try: 
     132        path = cpg.request.path 
     133    except: 
     134        # At startup, we don't have a path yet 
     135        path = '/' 
     136    res = _getFor(path, key, '#NULL#', returnSection) 
     137    if res != '#NULL#': 
     138        return _cast(cast, res) 
     139    return _cast(cast, defaultValue) 
    74140 
    75141class CaseSensitiveConfigParser(ConfigParser.ConfigParser): 
     
    91157            fp.close() 
    92158 
    93 # Known options to cast: 
    94 cast = { 
    95     'server': { 
    96         'logToScreen': 'getboolean', 
    97         'socketPort': 'getint', 
    98         'reverseDNS': 'getboolean', 
    99         'socketQueueSize': 'getint', 
    100         'threadPool': 'getint'}, 
    101     'session': { 
    102         'sessionTimeout': 'getint', 
    103         'cleanUpDelay': 'getint', 
    104     } 
    105 } 
    106          
    107159def _load(configFile = None): 
    108160    """ Convert an INI file to a dictionary """ 
     
    123175            configMap[section] = {} 
    124176        for option in configParser.options(section): 
    125             # Check if we need to cast options 
    126             funcName = cast.get(section, {}).get(option, 'get') 
    127             value = getattr(configParser, funcName)(section, option) 
     177            value = configParser.get(section, option) 
    128178            configMap[section][option] = value 
    129179 
     
    131181    _cpLogMessage = _cputil.getSpecialFunction('_cpLogMessage') 
    132182    _cpLogMessage("Server parameters:", 'CONFIG') 
    133     _cpLogMessage("  server.logToScreen: %s" % cpg.config.get('server', 'logToScreen'), 'CONFIG') 
    134     _cpLogMessage("  server.logFile: %s" % cpg.config.get('server', 'logFile'), 'CONFIG') 
    135     _cpLogMessage("  server.protocolVersion: %s" % cpg.config.get('server', 'protocolVersion'), 'CONFIG') 
    136     _cpLogMessage("  server.socketHost: %s" % cpg.config.get('server', 'socketHost'), 'CONFIG') 
    137     _cpLogMessage("  server.socketPort: %s" % cpg.config.get('server', 'socketPort'), 'CONFIG') 
    138     _cpLogMessage("  server.socketFile: %s" % cpg.config.get('server', 'socketFile'), 'CONFIG') 
    139     _cpLogMessage("  server.reverseDNS: %s" % cpg.config.get('server', 'reverseDNS'), 'CONFIG') 
    140     _cpLogMessage("  server.socketQueueSize: %s" % cpg.config.get('server', 'socketQueueSize'), 'CONFIG') 
    141     _cpLogMessage("  server.threadPool: %s" % cpg.config.get('server', 'threadPool'), 'CONFIG') 
    142     _cpLogMessage("  session.storageType: %s" % cpg.config.get('session', 'storageType'), 'CONFIG') 
    143     if cpg.config.get('session', 'storageType'): 
    144         _cpLogMessage("  session.timeout: %s min" % cpg.config.get('session', 'timeout'), 'CONFIG') 
    145         _cpLogMessage("  session.cleanUpDelay: %s min" % cpg.config.get('session', 'cleanUpDelay'), 'CONFIG') 
    146         _cpLogMessage("  session.cookieName: %s" % cpg.config.get('session', 'cookieName'), 'CONFIG') 
    147         _cpLogMessage("  session.storageFileDir: %s" % cpg.config.get('session', 'storageFileDir'), 'CONFIG') 
     183    _cpLogMessage("  server.env: %s" % cpg.config.get('server.env'), 'CONFIG') 
     184    _cpLogMessage("  server.logToScreen: %s" % cpg.config.get('server.logToScreen', cast='bool'), 'CONFIG') 
     185    _cpLogMessage("  server.logFile: %s" % cpg.config.get('server.logFile'), 'CONFIG') 
     186    _cpLogMessage("  server.protocolVersion: %s" % cpg.config.get('server.protocolVersion'), 'CONFIG') 
     187    _cpLogMessage("  server.socketHost: %s" % cpg.config.get('server.socketHost'), 'CONFIG') 
     188    _cpLogMessage("  server.socketPort: %s" % cpg.config.get('server.socketPort', cast='int'), 'CONFIG') 
     189    _cpLogMessage("  server.socketFile: %s" % cpg.config.get('server.socketFile'), 'CONFIG') 
     190    _cpLogMessage("  server.reverseDNS: %s" % cpg.config.get('server.reverseDNS', cast='bool'), 'CONFIG') 
     191    _cpLogMessage("  server.socketQueueSize: %s" % cpg.config.get('server.socketQueueSize', cast='int'), 'CONFIG') 
     192    _cpLogMessage("  server.threadPool: %s" % cpg.config.get('server.threadPool', cast='int'), 'CONFIG') 
     193    _cpLogMessage("  session.storageType: %s" % cpg.config.get('session.storageType'), 'CONFIG') 
     194    if cpg.config.get('session.storageType'): 
     195        _cpLogMessage("  session.timeout: %s min" % cpg.config.get('session.timeout', cast='float'), 'CONFIG') 
     196        _cpLogMessage("  session.cleanUpDelay: %s min" % cpg.config.get('session.cleanUpDelay', cast='float'), 'CONFIG') 
     197        _cpLogMessage("  session.cookieName: %s" % cpg.config.get('session.cookieName'), 'CONFIG') 
     198        _cpLogMessage("  session.storageFileDir: %s" % cpg.config.get('session.storageFileDir'), 'CONFIG') 
    148199    _cpLogMessage("  staticContent: %s" % cpg.config.get('staticContent'), 'CONFIG') 
    149200 
  • trunk/cherrypy/_cpdefaults.py

    r199 r202  
    3232""" 
    3333 
    34 import time, thread, os, cpg 
     34import time, thread, os 
    3535import cPickle as pickle 
     36import cpg 
    3637 
    3738def _cpLogMessage(msg, context = '', severity = 0): 
     
    4950        lebel = "UNKNOWN" 
    5051    try: 
    51         logToScreen = int(cpg.configOption.logToScreen
     52        logToScreen = int(cpg.config.get('server.logToScreen', cast='bool')
    5253    except: 
    5354        logToScreen = True 
     
    5556    if logToScreen: 
    5657        print s 
    57     if cpg.config.get('server', 'logFile'): 
    58         f = open(cpg.config.get('server','logFile'), 'ab') 
     58    if cpg.config.get('server.logFile'): 
     59        f = open(cpg.config.get('server.logFile'), 'ab') 
    5960        f.write(s + '\n') 
    6061        f.close() 
     
    7576 
    7677    if threadPool is None: 
    77         threadPool = cpg.config.get('server', 'threadPool') 
     78        threadPool = cpg.config.get('server.threadPool', cast='int') 
    7879    if sessionStorageType is None: 
    79         sessionStorageType = cpg.config.get('session', 'storageType') 
     80        sessionStorageType = cpg.config.get('session.storageType') 
    8081    if sessionStorageFileDir is None: 
    81         sessionStorageFileDir = cpg.config.get('session', 'storageFileDir') 
     82        sessionStorageFileDir = cpg.config.get('session.storageFileDir') 
    8283 
    8384    t = time.localtime(expirationTime) 
     
    103104 
    104105    if threadPool is None: 
    105         threadPool = cpg.config.get('server', 'threadPool') 
     106        threadPool = cpg.config.get('server.threadPool', cast='int') 
    106107    if sessionStorageType is None: 
    107         sessionStorageType = cpg.config.get('session', 'storageType') 
     108        sessionStorageType = cpg.config.get('session.storageType') 
    108109    if sessionStorageFileDir is None: 
    109         sessionStorageFileDir = cpg.config.get('session', 'storageFileDir') 
     110        sessionStorageFileDir = cpg.config.get('session.storageFileDir') 
    110111 
    111112    if sessionStorageType == "ram": 
     
    132133 
    133134    if threadPool is None: 
    134         threadPool = cpg.config.get('server', 'threadPool') 
     135        threadPool = cpg.config.get('server.threadPool', cast='int') 
    135136    if sessionStorageType is None: 
    136         sessionStorageType = cpg.config.get('session', 'storageType') 
     137        sessionStorageType = cpg.config.get('session.storageType') 
    137138    if sessionStorageFileDir is None: 
    138         sessionStorageFileDir = cpg.config.get('session', 'storageFileDir') 
     139        sessionStorageFileDir = cpg.config.get('session.storageFileDir') 
    139140 
    140141    # Clean up old session data 
     
    165166 
    166167_cpFilterList = [] 
     168 
     169# Filters that are always included 
     170from cherrypy.lib.filter import baseurlfilter, cachefilter, \ 
     171    decodingfilter, encodingfilter, gzipfilter, logdebuginfofilter, \ 
     172    staticfilter, tidyfilter, virtualhostfilter, xmlrpcfilter 
     173_cpDefaultInputFilterList = [ 
     174    cachefilter.CacheInputFilter(), 
     175    logdebuginfofilter.LogDebugInfoInputFilter(), 
     176    virtualhostfilter.VirtualHostFilter(), 
     177    baseurlfilter.BaseUrlFilter(), 
     178    decodingfilter.DecodingFilter(), 
     179    staticfilter.StaticFilter(), 
     180    xmlrpcfilter.XmlRpcInputFilter(), 
     181] 
     182_cpDefaultOutputFilterList = [ 
     183    xmlrpcfilter.XmlRpcOutputFilter(), 
     184    encodingfilter.EncodingFilter(), 
     185    tidyfilter.TidyFilter(), 
     186    logdebuginfofilter.LogDebugInfoOutputFilter(), 
     187    gzipfilter.GzipFilter(), 
     188    cachefilter.CacheOutputFilter(), 
     189] 
     190 
  • trunk/cherrypy/_cphttpserver.py

    r199 r202  
    3838    # If sessions are stored in files and we 
    3939    # use threading, we need a lock on the file 
    40     if (cpg.config.get('server', 'threadPool') > 1) and \ 
    41             cpg.config.get('session', 'storageType') == 'file': 
     40    if (cpg.config.get('server.threadPool', cast='int') > 1) and \ 
     41            cpg.config.get('session.storageType') == 'file': 
    4242        cpg._sessionFileLock = threading.RLock() 
    4343 
    4444 
    45     if cpg.config.get('server', 'socketFile'): 
     45    if cpg.config.get('server.socketFile'): 
    4646        # AF_UNIX socket 
    4747        # TODO: Handle threading here 
     
    4949    else: 
    5050        # AF_INET socket 
    51         if cpg.config.get('server', 'threadPool') > 1: 
     51        if cpg.config.get('server.threadPool', cast='int') > 1: 
    5252            MyCherryHTTPServer = PooledThreadServer 
    5353        else: 
    5454            MyCherryHTTPServer = CherryHTTPServer 
    5555 
    56     MyCherryHTTPServer.request_queue_size = cpg.config.get('server', 'socketQueueSize') 
     56    MyCherryHTTPServer.request_queue_size = cpg.config.get('server.socketQueueSize', cast='int') 
    5757 
    5858    # Set protocol_version 
    59     CherryHTTPRequestHandler.protocol_version = cpg.config.get('server', 'protocolVersion') 
     59    CherryHTTPRequestHandler.protocol_version = cpg.config.get('server.protocolVersion') 
    6060 
    6161    run_server(CherryHTTPRequestHandler, MyCherryHTTPServer, \ 
    62         (cpg.config.get('server', 'socketHost'), cpg.config.get('server', 'socketPort')), \ 
    63         cpg.config.get('server', 'socketFile')) 
     62        (cpg.config.get('server.socketHost'), cpg.config.get('server.socketPort', cast='int')), \ 
     63        cpg.config.get('server.socketFile')) 
    6464 
    6565def run_server(HandlerClass, ServerClass, server_address, socketFile): 
    6666    """Run the HTTP request handler class.""" 
    6767 
    68     if cpg.config.get('server', 'socketFile'): 
    69         try: os.unlink(cpg.config.get('server', 'socketFile')) # So we can reuse the socket 
     68    if cpg.config.get('server.socketFile'): 
     69        try: os.unlink(cpg.config.get('server.socketFile')) # So we can reuse the socket 
    7070        except: pass 
    71         server_address = cpg.config.get('server', 'socketFile') 
    72     if cpg.config.get('server', 'threadPool') > 1: 
    73         myCherryHTTPServer = ServerClass(server_address, cpg.config.get('server', 'threadPool'), HandlerClass) 
     71        server_address = cpg.config.get('server.socketFile') 
     72    if cpg.config.get('server.threadPool', cast='int') > 1: 
     73        myCherryHTTPServer = ServerClass(server_address, cpg.config.get('server.threadPool', cast='int'), HandlerClass) 
    7474    else: 
    7575        myCherryHTTPServer = ServerClass(server_address, HandlerClass) 
    7676    cpg._server = myCherryHTTPServer 
    77     if cpg.config.get('server', 'socketFile'): 
     77    if cpg.config.get('server.socketFile'): 
    7878        try: os.chmod(socketFile, 0777) # So everyone can access the socket 
    7979        except: pass 
     
    8282 
    8383    servingWhat = "HTTP" 
    84     if cpg.config.get('server', 'socketPort'):  
     84    if cpg.config.get('server.socketPort', cast='int'):  
    8585        onWhat = ("socket: ('%s', %s)" %  
    86                  (cpg.config.get('server', 'socketHost'), cpg.config.get('server', 'socketPort'))) 
    87     else: onWhat = "socket file: %s" % cpg.config.get('server', 'socketFile') 
     86                 (cpg.config.get('server.socketHost'), cpg.config.get('server.socketPort', cast='int'))) 
     87    else: onWhat = "socket file: %s" % cpg.config.get('server.socketFile') 
    8888    _cpLogMessage("Serving %s on %s" % (servingWhat, onWhat), 'HTTP') 
    8989 
     
    113113    def address_string(self): 
    114114        """ Try to do a reverse DNS based on [server]reverseDNS in the config file """ 
    115         if cpg.config.get('server', 'reverseDNS'): 
     115        if cpg.config.get('server.reverseDNS', cast='bool'): 
    116116            return BaseHTTPServer.BaseHTTPRequestHandler.address_string(self) 
    117117        else: 
  • trunk/cherrypy/_cphttptools.py

    r199 r202  
    3030import mimetypes, sha, random, string, _cputil, cperror, Cookie, urlparse 
    3131from lib.filter import basefilter 
     32import _cpdefaults 
    3233 
    3334""" 
     
    143144 
    144145def applyFilterList(methodName): 
    145     try: 
    146         filterList = _cputil.getSpecialFunction('_cpFilterList') 
    147         for filter in filterList: 
    148             method = getattr(filter, methodName, None) 
    149             if method: 
    150                 method() 
    151     except basefilter.InternalRedirect: 
    152         # If we get an InternalRedirect, we start the filter list   
    153         #   from scratch. Is cpg.request.path or cpg.request.objectPath 
    154         #   has been modified by the hook, then a new filter list 
    155         #   will be applied.   
    156         # We use recursion so if there is an infinite loop, we'll   
    157         #   get the regular python "recursion limit exceeded" exception.   
    158         applyFilterList(methodName)  
    159  
     146    filterList = _cpdefaults._cpDefaultInputFilterList + \ 
     147        _cputil.getSpecialFunction('_cpFilterList') + \ 
     148        _cpdefaults._cpDefaultOutputFilterList 
     149    for filter in filterList: 
     150        method = getattr(filter, methodName, None) 
     151        if method: 
     152            method() 
    160153 
    161154def insertIntoHeaderMap(key,value): 
     
    176169    cpg.request.objectPath = None  
    177170 
     171    applyFilterList('setConfig') 
    178172    applyFilterList('afterRequestHeader') 
    179173 
     
    187181    cpg.response.wfile = wfile 
    188182    cpg.response.sendResponse = True 
     183    cpg.response.body = None 
    189184 
    190185    # Prepare response variables 
     
    193188    date = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (weekdayname[wd], day, monthname[month], year, hh, mm, ss) 
    194189    cpg.response.headerMap = { 
    195         "protocolVersion": cpg.config.get('server', 'protocolVersion'), 
     190        "protocolVersion": cpg.config.get('server.protocolVersion'), 
    196191        "Status": "200 OK", 
    197192        "Content-Type": "text/html", 
     
    228223 
    229224            # Still save session data 
    230             if cpg.config.get('session', 'storageType') and not cpg.request.isStatic: 
    231                 sessionId = cpg.response.simpleCookie[cpg.config.get('session', 'cookieName')].value 
    232                 expirationTime = time.time() + cpg.config.get('session', 'timeout') * 60 
     225            if cpg.config.get('session.storageType') and not cpg.request.isStatic: 
     226                sessionId = cpg.response.simpleCookie[cpg.config.get('session.cookieName')].value 
     227                expirationTime = time.time() + cpg.config.get('session.timeout') * 60 
    233228                _cputil.getSpecialFunction('_cpSaveSessionData')(sessionId, cpg.request.sessionMap, expirationTime) 
    234229 
     230            applyFilterList('beforeErrorResponse') 
    235231            wfile.write('%s %s\r\n' % (cpg.response.headerMap['protocolVersion'], cpg.response.headerMap['Status'])) 
    236232 
     
    251247            for line in cpg.response.body: 
    252248                wfile.write(line) 
     249            applyFilterList('afterErrorResponse') 
    253250        except: 
    254251            bodyFile = StringIO.StringIO() 
    255252            traceback.print_exc(file = bodyFile) 
    256253            body = bodyFile.getvalue() 
    257             wfile.write('%s 200 OK\r\n' % cpg.config.get('server', 'protocolVersion')) 
     254            wfile.write('%s 200 OK\r\n' % cpg.config.get('server.protocolVersion')) 
    258255            wfile.write('Content-Type: text/plain\r\n') 
    259256            wfile.write('Content-Length: %s\r\n' % len(body)) 
     
    274271 
    275272    # Save session data 
    276     if cpg.config.get('session', 'storageType') and not cpg.request.isStatic: 
    277         sessionId = cpg.response.simpleCookie[cpg.config.get('session', 'cookieName')].value 
    278         expirationTime = time.time() + cpg.config.get('session', 'timeout') * 60 
     273    if cpg.config.get('session.storageType') and not cpg.request.isStatic: 
     274        sessionId = cpg.response.simpleCookie[cpg.config.get('session.cookieName')].value 
     275        expirationTime = time.time() + cpg.config.get('session.timeout', cast='float') * 60 
    279276        _cputil.getSpecialFunction('_cpSaveSessionData')(sessionId, cpg.request.sessionMap, expirationTime) 
    280277 
     
    301298    # Clean up expired sessions if needed: 
    302299    now = time.time() 
    303     if (cpg.config.get('session', 'storageType') and  
    304         cpg.config.get('session', 'cleanUpDelay') and  
    305         (cpg._lastSessionCleanUpTime + cpg.config.get('session', 'cleanUpDelay') * 60) <= now): 
     300    if (cpg.config.get('session.storageType') and  
     301        cpg.config.get('session.cleanUpDelay', cast='float') and  
     302        (cpg._lastSessionCleanUpTime + cpg.config.get('session.cleanUpDelay', cast='float') * 60) <= now): 
    306303        cpg._lastSessionCleanUpTime = now 
    307304        _cputil.getSpecialFunction('_cpCleanUpOldSessions')() 
     
    321318    path = urllib.unquote(path) # Replace quoted chars (eg %20) from url 
    322319 
    323     # Handle static directories 
    324     for urlDir, fsDir in cpg.config.get('staticContent').items(): 
    325         if path == urlDir or path[:len(urlDir)+1]==urlDir+'/': 
    326  
    327             cpg.request.isStatic = 1 
    328  
    329             fname = fsDir + path[len(urlDir):] 
    330             start_url_var = cpg.request.browserUrl.find('?') 
    331             if start_url_var != -1: fname = fname + cpg.request.browserUrl[start_url_var:]   
    332             try: 
    333                 stat = os.stat(fname) 
    334             except OSError: 
    335                 raise cperror.NotFound(path) 
    336             modifTime = stat.st_mtime 
    337  
    338             strModifTime = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(modifTime)) 
    339  
    340             # Check if browser sent "if-modified-since" in request header 
    341             if cpg.request.headerMap.has_key('If-Modified-Since'): 
    342                 # Check if if-modified-since date is the same as strModifTime 
    343                 if cpg.request.headerMap['If-Modified-Since'] == strModifTime: 
    344                     cpg.response.headerMap = { 
    345                         'Status': 304,  
    346                         'protocolVersion': cpg.config.get('server', 'protocolVersion'), 
    347                         'Date': cpg.response.headerMap['Date']} 
    348                     cpg.response.body = [] 
    349                     sendResponse(wfile) 
    350                     return 
    351  
    352             cpg.response.headerMap['Last-Modified'] = strModifTime 
    353             # Set Content-Length and use an iterable (file object) 
    354             #   this way CP won't load the whole file in memory 
    355             cpg.response.headerMap['Content-Length'] = stat[6] 
    356             cpg.response.body = open(fname, 'rb') 
    357             # Set content-type based on filename extension 
    358             i = path.rfind('.') 
    359             if i != -1: ext = path[i:] 
    360             else: ext = "" 
    361             contentType = mimetypes.types_map.get(ext, "text/plain") 
    362             cpg.response.headerMap['Content-Type'] = contentType 
    363             sendResponse(wfile) 
    364             return 
    365  
    366320    # Get session data 
    367     if cpg.config.get('session', 'storageType') and not cpg.request.isStatic: 
     321    if cpg.config.get('session.storageType') and not cpg.request.isStatic: 
    368322        now = time.time() 
    369323        # First, get sessionId from cookie 
    370         try: sessionId = cpg.request.simpleCookie[cpg.config.get('session', 'cookieName')].value 
     324        try: sessionId = cpg.request.simpleCookie[cpg.config.get('session.cookieName')].value 
    371325        except: sessionId=None 
    372326        if sessionId: 
     
    388342            cpg.request.sessionMap['_sessionId'] = sessionId 
    389343 
    390         cpg.response.simpleCookie[cpg.config.get('session', 'cookieName')] = sessionId 
    391         cpg.response.simpleCookie[cpg.config.get('session', 'cookieName')]['path'] = '/' 
    392         cpg.response.simpleCookie[cpg.config.get('session', 'cookieName')]['version'] = 1 
    393  
    394     try: 
    395         func, objectPathList, virtualPathList = mapPathToObject() 
    396     except IndexRedirect, inst: 
    397         # For an IndexRedirect, we don't go through the regular 
    398         #   mechanism: we return the redirect immediately 
    399         newUrl = urlparse.urljoin(cpg.request.base, inst.args[0]) 
    400         wfile.write('%s 302\r\n' % (cpg.response.headerMap['protocolVersion'])) 
    401         cpg.response.headerMap['Location'] = newUrl 
    402         for key, valueList in cpg.response.headerMap.items(): 
    403             if key not in ('Status', 'protocolVersion'): 
    404                 if type(valueList) != type([]): valueList = [valueList] 
    405                 for value in valueList: 
    406                     wfile.write('%s: %s\r\n'%(key, value)) 
    407         wfile.write('\r\n') 
    408         return 
    409           
    410     # Remove "root" from objectPathList and join it to get objectPath 
    411     cpg.request.objectPath = '/' + '/'.join(objectPathList[1:]) 
    412     body = func(*(virtualPathList + cpg.request.paramList), **(cpg.request.paramMap)) 
     344        cpg.response.simpleCookie[cpg.config.get('session.cookieName')] = sessionId 
     345        cpg.response.simpleCookie[cpg.config.get('session.cookieName')]['path'] = '/' 
     346        cpg.response.simpleCookie[cpg.config.get('session.cookieName')]['version'] = 1 
     347 
     348    if cpg.response.body is None: 
     349        try: 
     350            func, objectPathList, virtualPathList = mapPathToObject() 
     351        except IndexRedirect, inst: 
     352            # For an IndexRedirect, we don't go through the regular 
     353            #   mechanism: we return the redirect immediately 
     354            newUrl = urlparse.urljoin(cpg.request.base, inst.args[0]) 
     355            wfile.write('%s 302\r\n' % (cpg.response.headerMap['protocolVersion'])) 
     356            cpg.response.headerMap['Location'] = newUrl 
     357            for key, valueList in cpg.response.headerMap.items(): 
     358                if key not in ('Status', 'protocolVersion'): 
     359                    if type(valueList) != type([]): valueList = [valueList] 
     360                    for value in valueList: 
     361                        wfile.write('%s: %s\r\n'%(key, value)) 
     362            wfile.write('\r\n') 
     363            return 
     364              
     365        # Remove "root" from objectPathList and join it to get objectPath 
     366        cpg.request.objectPath = '/' + '/'.join(objectPathList[1:]) 
     367        body = func(*(virtualPathList + cpg.request.paramList), **(cpg.request.paramMap)) 
     368    else: 
     369        body = cpg.response.body 
    413370 
    414371    # builds a uniform return type 
  • trunk/cherrypy/lib/filter/basefilter.py

    r141 r202  
    2727""" 
    2828 
    29 class InternalRedirect(Exception): pass 
    3029class RequestHandled(Exception): pass 
    3130 
     
    5655        pass 
    5756 
     57    def beforeErrorResponse(self): 
     58        """ Called before starting to write response, after _cpOnError has 
     59            been called 
     60        """ 
     61        pass 
     62 
     63    def afterErrorResponse(self): 
     64        """ Called after writing the response, after _cpOnError has 
     65            been called 
     66        """ 
     67        pass 
     68 
  • trunk/cherrypy/lib/filter/baseurlfilter.py

    r129 r202  
    2828 
    2929from basefilter import BaseInputFilter 
    30 from cherrypy import cpg 
    3130 
    3231class BaseUrlFilter(BaseInputFilter): 
     
    3635    """ 
    3736 
    38     def __init__(self, baseUrl = 'http://localhost', useXForwardedHost = True): 
    39         # New baseUrl 
    40         self.baseUrl = baseUrl 
    41         self.useXForwardedHost = useXForwardedHost 
     37    # def __init__(self, baseUrl = 'http://localhost', useXForwardedHost = True): 
     38    #     # New baseUrl 
     39    #     self.baseUrl = baseUrl 
     40    #     self.useXForwardedHost = useXForwardedHost 
     41 
     42    def setConfig(self): 
     43        # We have to dynamically import cpg because Python can't handle 
     44        #   circular module imports :-( 
     45        global cpg 
     46        from cherrypy import cpg 
     47        cpg.threadData.baseUrlFilterOn = cpg.config.get('baseUrlFilter', False, cast='bool') 
     48        cpg.threadData.baseUrlFilterBaseUrl = cpg.config.get('baseUrlFilter.baseUrl', 'http://localhost') 
     49        cpg.threadData.baseUrlFilterUseXForwardedHost = cpg.config.get('baseUrlFilter.useXForwardedHost', True, cast='bool') 
    4250 
    4351    def afterRequestHeader(self): 
    44         if self.useXForwardedHost: 
    45             newBaseUrl = cpg.request.headerMap.get("X-Forwarded-Host", self.baseUrl) 
     52        if not cpg.threadData.baseUrlFilterOn: 
     53            return 
     54        if cpg.threadData.baseUrlFilterUseXForwardedHost: 
     55            newBaseUrl = cpg.request.headerMap.get("X-Forwarded-Host", cpg.threadData.baseUrlFilterBaseUrl) 
    4656        else: 
    47             newBaseUrl = self.baseUrl 
     57            newBaseUrl = cpg.threadData.baseUrlFilterBaseUrl 
    4858        if newBaseUrl.find("://") == -1: 
    4959            # add http:// or https:// if needed  
  • trunk/cherrypy/lib/filter/cachefilter.py

    r142 r202  
    3232import cStringIO 
    3333 
    34 from basefilter import BaseInputFilter, RequestHandled 
    35 from cherrypy import cpg 
     34from basefilter import BaseInputFilter, BaseOutputFilter, RequestHandled 
    3635 
    3736def defaultCacheKey(): 
     
    139138            self.cache[objKey] = (expirationTime, lastModified, obj) 
    140139 
    141 class CacheInputFilter(BaseInputFilter): 
     140class SetConfig: 
     141    def setConfig(self): 
     142        # We have to dynamically import cpg because Python can't handle 
     143        #   circular module imports :-( 
     144        global cpg 
     145        from cherrypy import cpg 
     146        cpg.threadData.cacheFilterOn = cpg.config.get('cacheFilter', False, cast='bool') 
     147        if cpg.threadData.cacheFilterOn and not hasattr(cpg, '_cache'): 
     148            cpg._cache = self.CacheClass(self.key, self.delay, 
     149                self.maxobjsize, self.maxsize, self.maxobjects) 
     150 
     151 
     152class CacheInputFilter(BaseInputFilter, SetConfig): 
    142153    """ 
    143154    Works on the input chain. If the page is already stored in the cache 
     
    156167            maxobjects=1000    # 1000 objects 
    157168            ): 
    158         cpg._cache = CacheClass(key, delay, maxobjsize, maxsize, maxobjects) 
     169        self.CacheClass = CacheClass 
     170        self.key = key 
     171        self.delay = delay 
     172        self.maxobjsize = maxobjsize 
     173        self.maxsize = maxsize 
     174        self.maxobjects = maxobjects 
    159175     
    160176    def afterRequestBody(self): 
    161177        """ Checks if the page is already in the cache """ 
     178        if not cpg.threadData.cacheFilterOn: 
     179            return 
    162180        cacheData = cpg._cache.get() 
    163181        if cacheData: 
     
    165183            # found a hit! check the if-modified-since request header 
    166184            modifiedSince = cpg.request.headerMap.get('If-Modified-Since', None) 
    167             print "Cache hit: If-Modified-Since=%s, lastModified=%s" % (modifiedSince, lastModified) 
    168             if modifiedSince == lastModified: 
     185            # print "Cache hit: If-Modified-Since=%s, lastModified=%s" % (modifiedSince, lastModified) 
     186            if (modifiedSince is not None) and \ 
     187                    (modifiedSince == lastModified): 
    169188                cpg._cache.totNonModified += 1 
    170189                # the code below was borrowed from the sendResponse function 
    171190                # it should be refactored & put into a function to allow reuse 
    172                 cpg.response.wfile.write('%s %s\r\n' % (cpg.configOption.protocolVersion, 304)) 
     191                cpg.response.wfile.write('%s %s\r\n' % (cpg.config.get('server.protocolVersion'), 304)) 
    173192                # the code below doesn't work because the data isn't available at this point... 
    174193                #cpg.response.wfile.write('%s: %s\r\n' % ('Date', cpg.request.headerMap['Date'])) 
     
    185204            cpg.threadData.cacheable = True 
    186205 
    187 class CacheOutputFilter(object): 
     206class CacheOutputFilter(BaseOutputFilter, SetConfig): 
    188207    """ 
    189208    Works on the output chain. Stores the content of the page in the cache. 
     
    198217        is written. 
    199218        """ 
     219        if not cpg.threadData.cacheFilterOn: 
     220            return 
    200221        if isinstance(cpg.response.wfile, Tee): 
    201222            if cpg.threadData.cacheable: 
     
    210231        Close & fix the cache entry after content was fully written 
    211232        """ 
     233        if not cpg.threadData.cacheFilterOn: 
     234            return 
    212235        if isinstance(cpg.response.wfile, Tee): 
    213236            wrapper = cpg.response.wfile 
  • trunk/cherrypy/lib/filter/decodingfilter.py

    r170 r202  
    2828 
    2929from basefilter import BaseInputFilter 
    30 from cherrypy import cpg 
    31 import types 
    3230 
    3331class DecodingFilter(BaseInputFilter): 
     
    3634    """ 
    3735 
    38     def __init__(self, encoding = 'utf-8'): 
    39         self.encoding = encoding 
     36    # def __init__(self, encoding = 'utf-8'): 
     37    #     self.encoding = encoding 
     38 
     39    def setConfig(self): 
     40        # We have to dynamically import cpg because Python can't handle 
     41        #   circular module imports :-( 
     42        global cpg 
     43        from cherrypy import cpg 
     44        cpg.threadData.decodingFilterOn = cpg.config.get('decodingFilter', False, cast='bool') 
     45        cpg.threadData.decodingFilterEncoding = cpg.config.get('decodingFilter.encoding', 'utf-8') 
    4046 
    4147    def afterRequestBody(self): 
     48        if not cpg.threadData.decodingFilterOn: 
     49            return 
    4250        for key, value in cpg.request.paramMap.items(): 
    4351            if cpg.request.filenameMap.get(key): 
     
    4654            if isinstance(value, list): 
    4755                # value is a list: decode each element 
    48                 newValue = [v.decode(self.encoding) for v in value] 
     56                newValue = [v.decode(cpg.threadData.decodingFilterEncoding) for v in value] 
    4957            else: 
    5058                # value is a regular string: decode it 
    51                 newValue = value.decode(self.encoding) 
     59                newValue = value.decode(cpg.threadData.decodingFilterEncoding) 
    5260            cpg.request.paramMap[key] = newValue 
    5361 
  • trunk/cherrypy/lib/filter/encodingfilter.py

    r141 r202  
    2828 
    2929from basefilter import BaseOutputFilter 
    30 from cherrypy import cpg 
    3130import types 
    3231 
     
    3534    Filter that automatically encodes the response. 
    3635    """ 
    37  
    38     def __init__(self, encoding = 'utf-8', mimeTypeList = ['text/html']): 
    39         self.encoding = encoding 
    40         self.mimeTypeList = mimeTypeList 
     36    def setConfig(self): 
     37        # We have to dynamically import cpg because Python can't handle 
     38        #   circular module imports :-( 
     39        global cpg 
     40        from cherrypy import cpg 
     41        cpg.threadData.encodingFilterOn = cpg.config.get('encodingFilter', False, cast='bool') 
     42        cpg.threadData.encodingFilterEncoding = cpg.config.get('encodingFilter.encoding', 'utf-8') 
     43        cpg.threadData.encodingFilterMimeTypeList = cpg.config.get('encodingFilter.mimeTypeList', ['text/html'], cast='list') 
    4144 
    4245    def beforeResponse(self): 
     46        if not cpg.threadData.encodingFilterOn: 
     47            return 
    4348        contentType = cpg.response.headerMap.get("Content-Type") 
    4449        if contentType: 
    4550            ctlist = contentType.split(';')[0] 
    46             if (ctlist in self.mimeTypeList): 
     51            if (ctlist in cpg.threadData.encodingFilterMimeTypeList): 
    4752                # Add "charset=..." to response Content-Type header 
    4853                if contentType and 'charset' not in contentType: 
    49                     cpg.response.headerMap["Content-Type"] += ";charset=%s" % self.encoding 
     54                    cpg.response.headerMap["Content-Type"] += ";charset=%s" % cpg.threadData.encodingFilterEncoding 
    5055                # Return a generator that encodes the sequence 
    5156                cpg.response.body = self.encode_body(cpg.response.body) 
     
    5358    def encode_body(self, body): 
    5459        for line in body: 
    55             yield line.encode(self.encoding) 
     60            yield line.encode(cpg.threadData.encodingFilterEncoding) 
  • trunk/cherrypy/lib/filter/gzipfilter.py

    r108 r202  
    3131import time 
    3232from basefilter import BaseOutputFilter 
    33 from cherrypy import cpg 
    3433 
    3534class GzipFilter(BaseOutputFilter): 
     
    3736    Filter that gzips the response. 
    3837    """ 
    39  
    40     def __init__(self, mimeTypeList = ['text/html'], compresslevel=9): 
    41         # List of mime-types to compress 
    42         self.mimeTypeList = mimeTypeList 
    43         self.compresslevel = compresslevel 
     38    def setConfig(self): 
     39        # We have to dynamically import cpg because Python can't handle 
     40        #   circular module imports :-( 
     41        global cpg 
     42        from cherrypy import cpg 
     43        cpg.threadData.gzipFilterOn = cpg.config.get('gzipFilter', False, cast='bool') 
     44        cpg.threadData.gzipFilterMimeTypeList = cpg.config.get('gzipFilter.mimeTypeList', ['text/html'], cast='list') 
     45        cpg.threadData.gzipFilterCompressLevel = cpg.config.get('gzipFilter.compresslevel', 9, cast='int') 
    4446 
    4547    def beforeResponse(self): 
     48        if not cpg.threadData.gzipFilterOn: 
     49            return 
    4650        if not cpg.response.body: 
    4751            # Response body is empty (might be a 304 for instance) 
     
    4953        ct = cpg.response.headerMap.get('Content-Type').split(';')[0] 
    5054        ae = cpg.request.headerMap.get('Accept-Encoding', '') 
    51         if (ct in self.mimeTypeList) and ('gzip' in ae): 
     55        if (ct in cpg.threadData.gzipFilterMimeTypeList) and ('gzip' in ae): 
    5256            # Set header 
    5357            cpg.response.headerMap['Content-Encoding'] = 'gzip' 
     
    7781        crc = zlib.crc32("") 
    7882        size = 0 
    79         zobj = zlib.compressobj(self.compresslevel, zlib.DEFLATED, -zlib.MAX_WBITS, zlib.DEF_MEM_LEVEL, 0) 
     83        zobj = zlib.compressobj(cpg.threadData.gzipFilterCompressLevel, zlib.DEFLATED, -zlib.MAX_WBITS, zlib.DEF_MEM_LEVEL, 0) 
    8084        for line in body: 
    8185            s