20. Session Management

You may use the Rack middlewares for Session Management.

The some middlewares are listed in middlewares.rb as following this chapter.

Most Common Options

There are the three Rack middlewares in middlewares.rb which for managing sessions. They are listed in middlewares.rb after installing Nekonote Framework

The most common directives are listed below.

Some of the common directives wont't be used. It depends on the middlewares.

varibale name type description default
_key string A cookie name to store a session ID. When using Session::Dalli you shold set ‘namespace’ directive instead. rack.session
_domain string The cookie is sent to the web server when the accessing domain name (includes sub domain) matched the value set here. When you haven’t set anything or setting nil, ‘Domain=domain-value’ won’t be append to the value of ‘Set-Cookie’ header. -
_path string The cookie is sent to the web server when the accessing URL includes the path set here. ‘/’ matches any paths. /
_expire_after int Lefetime of the session cookie. When you haven’t set this option or setting nil, the cookie is a persistent cookie.  
_secure boolean True to a cookie is set and is sent when the web server is using SSL. false
_httponly boolean Accessibility of a cookie from javascript. Setting true to cookie is HttpOnly and can not access the cookie from javascript. false
_sidbits int Length of session ID. The default value is 128 bits. 128

Optional Directives For Session::Pool

variable name type description default
_drop boolean True to session data will be deleted precisely from the session cache. false

Required Directives For Session::Dalli

Session::Dalli uses memcached servers for storing session data. There are the options to configure memcached servers. More information is later point of this chapter.

varibale name type description example
_servers array Information of the memcached server to add. Need to set as “host:port:weight”. ‘port’ and ‘weight’ are optional. It’s possible to set any number of servers by comma. [‘127.0.0.1:11211’]
_connection_pooling boolean True to enabling connection pooling. False to disabling connection pooling false

Optional Directives For Session::Dalli

varibale name type description default
namespace string Namespace for keys in the memcached servers. The key is set similar “<namespace specified here>:<session ID>”. rack.session
failover boolean True to enabling failover and if the memcached server is down, the other available memcached server responds instead. You need to set more than one servers at the ‘server’ directive. true
threadsafe boolean True to thread-safe access to a socket. False to allow no thread-safe access. true
expires_in int TTL (Time to live) for cookie in seconds. The default is 0 and the meaning of 0 is forever. 0
compress boolean True to when the data is larger than 1024 bytes, it’s compressed and is sent to the memcached server. False to no compression. false

Connection pooling enables reusing the connections to access the memcached server quickly. In order to enable it, please set _connection_pooling = true.

The following directives is about connection pooling.

varibale name type description default
_size int Maximum number of connections a pool. 5
_timeout int Maximum time in seconds of making a connection from the connection pool. 5

Session::Cookie

Session::Cookie provides cookie based simple session management.

Session ID and session data are stored in a cookie.

There is a risk that session data can be changed through editing cookie. So this way is not secure.

You are not supposed to set some important data if enabling this feature. On top of that 4 kilobyte is maximum amount of storing cookie.

preference/your_environment/middlewares.rb

use Rack::Session::Cookie, _session_options

Session::Pool

Session::Pool provides property-based session management.

Session data is stored in the web server, cookie is only used to store session ID.

It will work faster but keep in mind that session data is stored in the instance variable on Ruby. It means that session data is on memory and is gone after restarting the web server.

preference/your_environment/middlewares.rb

_drop = false
_session_pool_options = {
    :drop => _drop
}
use Rack::Session::Pool, _session_options.merge(_session_pool_options)

Session::Dalli

Session::Dalli provides memcached based session management. You must prepare memcached server to store session data.

Session data is stored in specific memcached server, cookie is only used to store session ID.

In order to enable this middleware you must install a library called dalli. Need to add 'dalli' to your Gemfile, and running bundle install for getting dalli.

preference/your_environment/middlewares.rb

_servers = ['127.0.0.1:11211'] # you may add any number of servers by comma
_connection_pooling = false

# options for dalli client
_namespace  = 'nekonote.session'
_failover   = true
_threadsafe = true
_expires_in = 0
_compress   = false
_dalli_client_options = {
    :namespace  => _namespace,
    :failover   => _failover,
    :threadsafe => _threadsafe,
    :expires_in => _expires_in,
    :compress   => _compress
}

# options for connection pooling
# they will work when connection pooling is enbaled
_size    = 5
_timeout = 5
_dalli_pool_options = {
    :size    => _size,
    :timeout => _timeout
}

# set-up dalli
require 'dalli'

if _connection_pooling
    # enabling connection pooling
    _dalli_client = ::Dalli::Client.new _servers, _dalli_client_options
    _cache = ::ConnectionPool::Wrapper.new(_pool_options) {_dalli_client}
else
    # disable connection pooling
    _cache = ::Dalli::Client.new _servers, _dalli_client_options
end

_dalli_options = {
    :cache => _cache
}
use Rack::Session::Dalli, _session_options.merge(_dalli_options)

Weight

You may specify any number of memcached servers to server directive. When you set two or more memcached servers there, you may specify its weight.

Weight means which memcached server is supposed to be used more frequently. Bigger number one is used more frequently than smaller number one.

preference/your_environment/middlewares.rb

_servers = ['127.0.0.1:11211:70', '127.0.0.1:1122:30']

The example above says, 127.0.0.1:1121 is supposed to be used more frequently than 127.0.0.1:1122.

Failover

When you set multiple memcached servers, you’d better enable the failover system.

Failover is enabled by default. If you need to disable failover you should set _failover to false in your middlewares.rb.

Stored data in memecached server will be lost when server has gone, but failover feature can keep using available memcached server even if some of servers has gone.

The Object For Session Management

Rack::Session::Abstract::SessionHash object is supposed to be set to an instance variable called @session in Handler classes.

When any middleware isn’t enabled which about session management, nil is set to @session instead.

Session won’t start automatically. Session starts when the following methods are called: @session[key] = value, @session.clear, @session.destroy, @session.update(hash), @session.replace(hash), @session.delete(key).

Instance Methods For Rack::Session::Abstract::SessionHash

The following are methods which can be called through the value of @session.

method description
@session.id Returns the session ID. It returns nil when session has not started.
@session[:key] = ‘value’ Sets a value to the session data with a specified key.
@session[:key] Returns the value from the session data by a specific key.
@session.has_key? :key Returns true if a specific key exists in the session data, in other case returns false.
@session.empty? Returns true if the session data is empty, in other case returns false.
@session.to_hash Returns the all session data as hash: {key => value}. When session has not started returns empty hash.
@session.clear Clears the all session data.
@session.delete :key Deletes the data from the session data by a specific key.
@session.update hash Adds the given hash to session data.
@session.replace hash Replaces the session data with a specific hash.

In order to get more information, Please visit http://www.rubydoc.info/github/rack/rack/Rack/Session/Abstract/SessionHash

Example

This is the usage example for session management.

class Friend
    def get_friend_id_list_from_db
        # implement me!
        friend_id_list = [1, 5, 17, 28]

        return friend_id_list
    end
end
class ExampleHandler < BaseHandler
    def index
        if @session.has_key? :friend
            # get the list of friend id from the session data
            friend_id_list = @session[:friend]

            logwrite 'get friend_id_list from session data'

        else
            # get the list of friend id from the database
            friend = ::Friend.new
            friend_id_list = friend.get_friend_id_list_from_db

            # cache data in the session data
            @session[:friend] = friend_id_list

            logwrite 'get friend_id_list from database'
        end

        logwrite friend_id_list
    end
end