Log in

tipfy.ext.session

This extension implements sessions using datastore, memcache or secure cookies. It also provides an interface to get and set flash messages and to set and delete secure cookies or ordinary cookies, and several convenient mixins for the RequestHandler.

Overview

Sessions in Tipfy use secure cookies to store the session data (for securecookie-based sessions) or the session id (for datastore and memcached-based sessions). Secure cookies are cookies that are not alterable from the client side because they add a checksum that is validated in the server when read.

For securecookie-based sessions, this means that all the session data is stored in the cookie, so the keys are still readable from the client as a normal cookie is. The data can't be altered, however, because the checksum will fail if someone tries to forge a cookie. This approach saves resources avoiding RPC calls while keeping the data safe from forgery attempts.

For datastore and memcache-based sessions, the data is saved in datastore and the secure cookie only stores a random session id that references the session entity or memcache record. This adds a little overhead as a record is saved each time the session data changes, but it may be appropriate if you are storing an amount of data not suitable for a cookie or don't want to expose the keys stored in the session.

Note:

All sessions in Tipfy are lazy: session values are only loaded when accessed, and only saved if they change.

Tipfy also tries to minimize the overhead of datastore-based sessions storing and reading the session data from memcache.

On the other hand, securecookie-based sessions are very lightweight but the amount of data you can store in a cookie is limited.

Quick start

Sessions are set in a per handler basis. To quickly implement sessions, add SessionMiddleware to the list of middleware in a handler, then extend it from SessionMixin. Session data will be available in the session attribute, a dictionary-like object. It is only loaded when accessed and any changes to it are saved at the end of the request. Here's an example:

from tipfy import RequestHandler, Response
from tipfy.ext.session import SessionMiddleware, SessionMixin

class MyHandler(RequestHandler, SessionMixin):
    middleware = [SessionMiddleware]

    def get(self, **kwargs):
        # Get a value from the session.
        res = self.session.get('test')
        if not res:
            res = 'Session does not have a test key.'
            # Set a value in the session.
            self.session['test'] = 'I am stored in the session!'

        return Response(res)

To use sessions, you must configure a secret key to be used for HMAC generation. Use a random, long string for this; this is what assures that the session cookies can't be changed in the client side. Just add this to config.py:

config.py

config['tipfy.ext.session'] = {
    'secret_key': 'some very very secret key',
}

Note:

Setting middleware and mixin to have sessions seems a lot verbose, but you don't need to do this for all your handlers. Instead, do this once in a common base handler, then make all your handlers extend that base handler.

Configuration

These are the configuration options available for this extension. The only required configuration key is secret_key; all others are optional.

  • secret_key: Secret key to generate session cookies. Set this to something random and unguessable. This value is required. Default is tipfy.REQUIRED_VALUE (an exception is raised if it is not set).
  • default_backend: Default session backend when none is specified. Built-in options are 'datastore', 'memcache' or 'securecookie'. Default is 'securecookie'.
  • cookie_name: Name of the cookie to save a session or session id. Default is 'tipfy.session'.
  • cookie_args: default keyword arguments to set a cookie or securecookie. Keys are:
    • session_expires: Session expiration time in seconds. Limits the duration of the contents of a cookie, even if a session cookie exists. If None, the contents lasts as long as the cookie is valid. Default is None.
    • max_age: Cookie max age in seconds. Limits the duration of a session cookie. If None, the cookie lasts until the client is closed. Default is None.
    • domain: Domain of the cookie. To work accross subdomains the domain must be set to the main domain with a preceding dot, e.g., cookies set for '.mydomain.org' will work in 'foo.mydomain.org' and 'bar.mydomain.org'. Default is None, which means that cookies will only work for the current subdomain.
    • path: Path in which the authentication cookie is valid. Default is '/'.
    • secure: Make the cookie only available via HTTPS.
    • httponly: Disallow JavaScript to access the cookie.
    • force: If True, force cookie to be saved on each request, even if the session data isn't changed. Default to False.

Mixins

The session extension has several RequestHandler mixins to provide convenient access to session related stuff inside handlers. Your handlers can extend one or more of these mixins, as you need. Let's take a look at each of them.

SessionMixin

This mixin adds a session attribute to the handler, a dictionary-like object. Changes in the session will be applied at the end of the request.

from tipfy import RequestHandler, Response
from tipfy.ext.session import SessionMiddleware, SessionMixin

class MyHandler(RequestHandler, SessionMixin):
    middleware = [SessionMiddleware]

    def get(self, **kwargs):
        # Get a value from the session.
        res = self.session.get('test')
        if not res:
            res = 'Session does not have a test key.'
            # Set a value in the session.
            self.session['test'] = 'I am stored in the session!'

        return Response(res)

It also adds a get_session() method, used to request a session that uses a different cookie name or back-end than the default configured one. This is generally not needed, but it is here as a convenient access to the session store API:

from tipfy import RequestHandler, Response
from tipfy.ext.session import SessionMiddleware, SessionMixin

class MyHandler(RequestHandler, SessionMixin):
    middleware = [SessionMiddleware]

    def get(self, **kwargs):
        # Get a session using the memcache back-end instead of the default
        # configured one.
        session = self.get_session(backend='memcache')

        # Get a value from the session.
        res = session.get('test')
        if not res:
            res = 'Session does not have a test key.'
            # Set a value in the session.
            session['test'] = 'I am stored in the memcache session!'

        return Response(res)

FlashMixin

This mixin adds get_flash() and set_flash() methods to the handler, to get and set flash messages. Flash messages are stored in the session and removed when read. They are usually used to set a message after a successful form submission and redirect.

from tipfy import RequestHandler, Response
from tipfy.ext.session import SessionMiddleware, FlashMixin

class MyHandler(RequestHandler, FlashMixin):
    middleware = [SessionMiddleware]

    def get(self, **kwargs):
        # Get a list of flash messages.
        res = self.get_flash()
        if not res:
            res = ['No flash messages were set.']
            # Add a new flash message to the list of flashes, for display during the
            # next request.
            self.set_flash('I am a flash message. I was set during the previous request!')

        return Response(''.join(res))

MessagesMixin

This mixin adds the attribute messages to the handler: a list to store system messages to be displayed to the user, such as alerts, form errors and success messages. Each "message" is a dictionary with the keys:

  • level: Message level. Common values are "success", "error", "info" or "alert".
  • body: Message contents.
  • title: Optional message title.
  • life: Message life time in seconds. User interface can implement a mechanism to make the message disappear after the elapsed time. If not set, the message is permanent.

Messages are added using the the method set_message().

Flash messages are loaded and added to the messages list automatically.

from tipfy import RequestHandler, Response
from tipfy.ext.session import SessionMiddleware, MessagesMixin

class MyHandler(RequestHandler, MessagesMixin):
    middleware = [SessionMiddleware]

    def get(self, **kwargs):
        if not self.messages:
            # Set a success message to be added to flash messages.
            self.messages.append('No messages were set.')
            self.set_message('success', 'This is a success message set '
                'using flash.', flash=True)

        return Response(str(self.messages))

CookieMixin

This mixin adds set_cookie() and delete_cookie() methods to the handler, to set and delete cookies even if you don't have built a Response object yet. Cookies normally need a response to be set or deleted, but with this mixin you can do this at any time inside a handler.

from tipfy import RequestHandler, Response
from tipfy.ext.session import SessionMiddleware, CookieMixin

class MyHandler(RequestHandler, CookieMixin):
    middleware = [SessionMiddleware]

    def get(self, **kwargs):
        # Set a cookie.
        self.set_cookie('test', 'I am stored in a cookie!')

        # Get a cookie from request.
        res = self.request.cookies.get('test', 'No cookies were set.')

        return Response(res)

SecureCookieMixin

This mixin adds a get_secure_cookie() method to the handler, to return a SecureCookie object, which is a dictionary-like object. If a secure cookie was saved in a previous request, it will load that cookie, otherwise a new one is returned.

Changes to the returned secure cookie are saved at the end of request.

from tipfy import RequestHandler, Response
from tipfy.ext.session import SessionMiddleware, SecureCookieMixin

class MyHandler(RequestHandler, SecureCookieMixin):
    middleware = [SessionMiddleware]

    def get(self, **kwargs):
        # Get a secure cookie.
        cookie = self.get_secure_cookie('my_cookie_name')

        # Get a message from the cookie.
        res = cookie.get('test')
        if not res:
            res = 'No message was stored in the secure cookie.'
            # Set a message.
            cookie['test'] = 'I am stored in a secure cookie!'

        return Response(res)

AllSessionMixins

This mixin combines all session mixins into one, so extending it will implement all the mixin APIs described above.

from tipfy import RequestHandler, Response
from tipfy.ext.session import SessionMiddleware, AllSessionMixins

class MyHandler(RequestHandler, AllSessionMixins):
    middleware = [SessionMiddleware]

    def get(self, **kwargs):
        # Get a secure cookie.
        cookie = self.get_secure_cookie('my_cookie_name')
        cookie['foo'] = 'bar'

        # Save something in the session.
        self.session['baz'] = 'ding'

        return Response('Session mixins are yummy!')

Extension Reference


Powered by Moe. Yeah, the name is Moe. Powered by Google App Engine