Skip to content

Instantly share code, notes, and snippets.

@mmerickel
Last active June 1, 2022 19:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmerickel/574506bdfb733f4b140d to your computer and use it in GitHub Desktop.
Save mmerickel/574506bdfb733f4b140d to your computer and use it in GitHub Desktop.
session proxy
cookie_state = {
'session_id': session_id,
'is_deleted': False,
}
def update_cookie(request, response):
exc = getattr(request, 'exception', None)
# exit early if there's an exception and the user specified
# to not set cookies on exception
if exc is not None and not cookie_on_exception:
return
if cookie_state['is_deleted']:
response.delete_cookie(...)
else:
session_id = cookie_state['session_id']
cookieval = signed_serialize(session_key, secret)
response.set_cookie(
cookie_name,
value=cookieval,
max_age=cookie_max_age,
domain=cookie_domain,
secure=cookie_secure,
httponly=cookie_httponly,
)
request.add_response_callback(update_cookie)
def creator():
cookie_state['session_id'] = id_generator()
cookie_state['is_deleted'] = False
return cookie_state['session_id']
def deleter():
cookie_state['is_deleted'] = True
class SessionState(object):
def __init__(self, managed_dict, created, timeout, new):
self.managed_dict = managed_dict
self.created = created
self.timeout = timeout
self.new = new
class RedisSession(object):
def __init__(
self,
redis,
timeout,
creator,
deleter,
serialize=cPickle.dumps,
deserialize=cPickle.loads,
):
self.redis = redis
self.default_timeout = timeout
self._creator = creator
self._deleter = deleter
self.serialize = serialize
self.deserialize = deserialize
self._session_state = None
def _load(self, session_id):
"""Called by the factory to preload a session."""
self.session_id = session_id
del self._session_state
@reify
def _session_state(self):
try:
if self.session_id is not None:
blob = self.from_redis()
if isinstance(blob, dict):
# bw-compat with old-style session blobs
managed_dict = blob
created = blob['created'] # is this even tracked atm?
timeout = blob['_rs_timeout']
return SessionState(managed_dict, created, timeout, False)
else:
# new-style session blob
managed_dict, created, timeout = blob
return SessionState(managed_dict, created, timeout, False)
except ValueError:
# session failed to deserialize for some reason
# we'll fall through and create a new one
pass
# grab a new session id from the lifecycle manager
self.session_id = self._creator()
return SessionState({}, time.time(), self.default_timeout, True)
def to_redis(self):
blob = self.managed_dict, self.created, self.timeout
return self.serialize(blob)
@property
def new(self):
return self._session_state.new
@property
def created(self):
return self._session_state.created
@property
def managed_dict(self):
return self._session_state.managed_dict
_timeout_getter = lambda self: self._session_state.timeout
def _timeout_setter(self, value):
self._session_state.timeout = timeout
self.changed()
timeout = property(_timeout_getter, _timeout_setter)
def invalidate(self):
self.clear()
del self._session_state
self.session_id = None
# notify the lifecycle manager that the current session is gone
self._deleter()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment