| # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) |
| # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php |
| |
| """ |
| Creates a session object. |
| |
| In your application, use:: |
| |
| environ['paste.flup_session_service'].session |
| |
| This will return a dictionary. The contents of this dictionary will |
| be saved to disk when the request is completed. The session will be |
| created when you first fetch the session dictionary, and a cookie will |
| be sent in that case. There's current no way to use sessions without |
| cookies, and there's no way to delete a session except to clear its |
| data. |
| """ |
| |
| from paste import httpexceptions |
| from paste import wsgilib |
| import flup.middleware.session |
| flup_session = flup.middleware.session |
| |
| # This is a dictionary of existing stores, keyed by a tuple of |
| # store type and parameters |
| store_cache = {} |
| |
| class NoDefault(object): |
| pass |
| |
| class SessionMiddleware(object): |
| |
| session_classes = { |
| 'memory': (flup_session.MemorySessionStore, |
| [('session_timeout', 'timeout', int, 60)]), |
| 'disk': (flup_session.DiskSessionStore, |
| [('session_timeout', 'timeout', int, 60), |
| ('session_dir', 'storeDir', str, '/tmp/sessions')]), |
| 'shelve': (flup_session.ShelveSessionStore, |
| [('session_timeout', 'timeout', int, 60), |
| ('session_file', 'storeFile', str, |
| '/tmp/session.shelve')]), |
| } |
| |
| |
| def __init__(self, app, |
| global_conf=None, |
| session_type=NoDefault, |
| cookie_name=NoDefault, |
| **store_config |
| ): |
| self.application = app |
| if session_type is NoDefault: |
| session_type = global_conf.get('session_type', 'disk') |
| self.session_type = session_type |
| try: |
| self.store_class, self.store_args = self.session_classes[self.session_type] |
| except KeyError: |
| raise KeyError( |
| "The session_type %s is unknown (I know about %s)" |
| % (self.session_type, |
| ', '.join(self.session_classes.keys()))) |
| kw = {} |
| for config_name, kw_name, coercer, default in self.store_args: |
| value = coercer(store_config.get(config_name, default)) |
| kw[kw_name] = value |
| self.store = self.store_class(**kw) |
| if cookie_name is NoDefault: |
| cookie_name = global_conf.get('session_cookie', '_SID_') |
| self.cookie_name = cookie_name |
| |
| def __call__(self, environ, start_response): |
| service = flup_session.SessionService( |
| self.store, environ, cookieName=self.cookie_name, |
| fieldName=self.cookie_name) |
| environ['paste.flup_session_service'] = service |
| |
| def cookie_start_response(status, headers, exc_info=None): |
| service.addCookie(headers) |
| return start_response(status, headers, exc_info) |
| |
| try: |
| app_iter = self.application(environ, cookie_start_response) |
| except httpexceptions.HTTPException as e: |
| headers = (e.headers or {}).items() |
| service.addCookie(headers) |
| e.headers = dict(headers) |
| service.close() |
| raise |
| except: |
| service.close() |
| raise |
| |
| return wsgilib.add_close(app_iter, service.close) |
| |
| def make_session_middleware(app, global_conf, |
| session_type=NoDefault, |
| cookie_name=NoDefault, |
| **store_config): |
| """ |
| Wraps the application in a session-managing middleware. |
| The session service can then be found in |
| ``environ['paste.flup_session_service']`` |
| """ |
| return SessionMiddleware( |
| app, global_conf=global_conf, |
| session_type=session_type, cookie_name=cookie_name, |
| **store_config) |