Home | History | Annotate | Download | only in paste
      1 # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
      2 # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
      3 
      4 """
      5 Creates a session object.
      6 
      7 In your application, use::
      8 
      9     environ['paste.flup_session_service'].session
     10 
     11 This will return a dictionary.  The contents of this dictionary will
     12 be saved to disk when the request is completed.  The session will be
     13 created when you first fetch the session dictionary, and a cookie will
     14 be sent in that case.  There's current no way to use sessions without
     15 cookies, and there's no way to delete a session except to clear its
     16 data.
     17 """
     18 
     19 from paste import httpexceptions
     20 from paste import wsgilib
     21 import flup.middleware.session
     22 flup_session = flup.middleware.session
     23 
     24 # This is a dictionary of existing stores, keyed by a tuple of
     25 # store type and parameters
     26 store_cache = {}
     27 
     28 class NoDefault(object):
     29     pass
     30 
     31 class SessionMiddleware(object):
     32 
     33     session_classes = {
     34         'memory': (flup_session.MemorySessionStore,
     35                    [('session_timeout', 'timeout', int, 60)]),
     36         'disk': (flup_session.DiskSessionStore,
     37                  [('session_timeout', 'timeout', int, 60),
     38                   ('session_dir', 'storeDir', str, '/tmp/sessions')]),
     39         'shelve': (flup_session.ShelveSessionStore,
     40                    [('session_timeout', 'timeout', int, 60),
     41                     ('session_file', 'storeFile', str,
     42                      '/tmp/session.shelve')]),
     43         }
     44 
     45 
     46     def __init__(self, app,
     47                  global_conf=None,
     48                  session_type=NoDefault,
     49                  cookie_name=NoDefault,
     50                  **store_config
     51                  ):
     52         self.application = app
     53         if session_type is NoDefault:
     54             session_type = global_conf.get('session_type', 'disk')
     55         self.session_type = session_type
     56         try:
     57             self.store_class, self.store_args = self.session_classes[self.session_type]
     58         except KeyError:
     59             raise KeyError(
     60                 "The session_type %s is unknown (I know about %s)"
     61                 % (self.session_type,
     62                    ', '.join(self.session_classes.keys())))
     63         kw = {}
     64         for config_name, kw_name, coercer, default in self.store_args:
     65             value = coercer(store_config.get(config_name, default))
     66             kw[kw_name] = value
     67         self.store = self.store_class(**kw)
     68         if cookie_name is NoDefault:
     69             cookie_name = global_conf.get('session_cookie', '_SID_')
     70         self.cookie_name = cookie_name
     71 
     72     def __call__(self, environ, start_response):
     73         service = flup_session.SessionService(
     74             self.store, environ, cookieName=self.cookie_name,
     75             fieldName=self.cookie_name)
     76         environ['paste.flup_session_service'] = service
     77 
     78         def cookie_start_response(status, headers, exc_info=None):
     79             service.addCookie(headers)
     80             return start_response(status, headers, exc_info)
     81 
     82         try:
     83             app_iter = self.application(environ, cookie_start_response)
     84         except httpexceptions.HTTPException as e:
     85             headers = (e.headers or {}).items()
     86             service.addCookie(headers)
     87             e.headers = dict(headers)
     88             service.close()
     89             raise
     90         except:
     91             service.close()
     92             raise
     93 
     94         return wsgilib.add_close(app_iter, service.close)
     95 
     96 def make_session_middleware(app, global_conf,
     97                             session_type=NoDefault,
     98                             cookie_name=NoDefault,
     99                             **store_config):
    100     """
    101     Wraps the application in a session-managing middleware.
    102     The session service can then be found in
    103     ``environ['paste.flup_session_service']``
    104     """
    105     return SessionMiddleware(
    106         app, global_conf=global_conf,
    107         session_type=session_type, cookie_name=cookie_name,
    108         **store_config)
    109