Skip to content

Instantly share code, notes, and snippets.

@cloverstd
Last active August 13, 2018 19:16
Show Gist options
  • Save cloverstd/7395139 to your computer and use it in GitHub Desktop.
Save cloverstd/7395139 to your computer and use it in GitHub Desktop.
Tornado Session
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tornado.web
import tornado.ioloop
import tornado.httpserver
from session import Session, RedisSessionBackend
import redis
class BaseHandler(tornado.web.RequestHandler):
pass
class IndexHandler(BaseHandler):
@Session
def get(self):
self.session["count"] += 1
self.write("hello")
self.write("%r" % self.session)
class SessionHandler(BaseHandler):
@Session
def get(self):
self.session["count"] = 0
self.session["permanent"] = True
self.session["login"] = True
self.write("%r" % self.session)
class TestHandler(BaseHandler):
@Session
def get(self):
self.session.pop("login")
self.write("Test")
class AllHandler(BaseHandler):
@Session
def get(self):
self.write("%r" % self.session)
class KillHandler(BaseHandler):
@Session
def get(self):
self.session.kill()
self.write("kill")
class Application(tornado.web.Application):
def __init__(self):
handlers = [(r'/', IndexHandler),
(r'/test', TestHandler),
(r'/s', AllHandler),
(r'/kill', KillHandler),
(r'/init', SessionHandler)]
settings = dict(debug=True,
cookie_secret="key")
super(Application, self).__init__(handlers=handlers, **settings)
self.redis = redis.StrictRedis()
self.session_backend = RedisSessionBackend(self.redis, secret_key="this is a key")
if __name__ == '__main__':
app = Application()
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(8888)
tornado.ioloop.IOLoop.instance().start()
# coding: utf-8
import os, time, base64
try:
import cPickle as pickle
except ImportError:
import pickle
try:
import hashlib
sha1 = hashlib.sha1
except ImportError:
import sha
sha1 = sha.new
def _generate_session_id(backend):
"""Generate a random id for session"""
while True:
rand = os.urandom(16)
now = time.time()
secret_key = backend.options["secret_key"]
session_id = sha1("%s%s%s" %(rand, now, secret_key))
session_id = session_id.hexdigest()
if not backend.exists(session_id):
break
return session_id
class SessionBackend(object):
"""
The base Session Backend class
"""
def getitem(self, key):
pass
def setitem(self, key, value, timeout):
pass
def delitem(self, key):
pass
def exists(self, key):
pass
def encode(self, session_dict):
"""encodes session dict as a string"""
pickled = pickle.dumps(session_dict)
return base64.encodestring(pickled)
def decode(self, session_data):
"""decodes the data to get back the session dict """
pickled = base64.decodestring(session_data)
return pickle.loads(pickled)
class RedisSessionBackend(SessionBackend):
def __init__(self, redis_connection, **options):
self.options = dict(prefix="Session ID:",
timeout=86400,
#cookie_name="session_id",
#cookie_domain=None,
#cookie_path=None,
secret_key="",
)
self.options.update(options)
self.redis = redis_connection
def getitem(self, key):
if self.exists(key):
pickled = self.redis.get(self.prefix(key))
return self.decode(pickled)
else:
#raise KeyError, key
return None
def setitem(self, key, value, timeout=None):
"""Default timeout: 24 * 60 * 60 seconds"""
pickled = self.encode(value)
self.redis.set(self.prefix(key), pickled)
if timeout:
self.redis.expire(self.prefix(key), timeout)
else:
self.redis.expire(self.prefix(key), self.options["timeout"])
def delitem(self, key):
self.redis.delete(self.prefix(key))
def exists(self, key):
return bool(self.redis.exists(self.prefix(key)))
def prefix(self, key):
return "%s%s" % (self.options["prefix"], key)
class SessionData(dict):
def __init__(self, session_id=None):
self.id = session_id
self.permanent = False
self.death = False
def __getitem__(self, key):
if self.has_key(key):
return dict.__getitem__(self, key)
return None
def kill(self):
self.death = True
def __setitem__(self, key, value):
dict.__setitem__(self, key, value)
#def __setattr__(self, key, value):
#self[key] = value
#def __getattr__(self, key):
#return self[key]
#def __delattr__(self, key):
#del self[key]
def Session(request):
import functools
@functools.wraps(request)
def Process(handler, *args):
session_id = handler.get_secure_cookie("session_id")
item = handler.application.session_backend.getitem(session_id)
data = None
if item:
data = SessionData(item.id)
data.update(item)
else:
data = SessionData()
handler.clear_cookie("session_id")
handler.__setattr__("session", data)
# excute request
result = request(handler, *args)
if data.id:
if data.death:
handler.clear_cookie("session_id")
handler.application.session_backend.delitem(data.id)
elif data["permanent"] == True:
handler.set_secure_cookie("session_id", data.id)
handler.application.session_backend.setitem(data.id, data, timeout=86400*31)
else:
handler.set_secure_cookie("session_id", data.id, expires_days=None)
handler.application.session_backend.setitem(data.id, data)
else:
if len(data.keys()):
data.id = _generate_session_id(handler.application.session_backend)
if data["permanent"] == True:
handler.set_secure_cookie("session_id", data.id)
handler.application.session_backend.setitem(data.id, data, timeout=86400*31)
else:
handler.set_secure_cookie("session_id", data.id, expires_days=None)
handler.application.session_backend.setitem(data.id, data)
return result
return Process
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment