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