If someone works with the same needs, I found that making a class for managing sessions inside an application was the easiest way.
Rack :: Utils has 2 bright shortcuts, Rack :: Utils.set_cookie_header! and Utils.delete_cookie_header! , which can simplify the work with cookies.
I save sessions in the database used by my application, but this should be trivial to support a different back-end.
As an additional note, a few considerations I came up with:
- To be sure that the cookie name is valid, I use sha-1 of the sub-application name for this purpose.
- SecureRandom.urlsafe_base64 is useful for generating a session key.
- Session cleanup and updating must be done manually.
Code example
A class that manages cookies, an installed commit function, and deletes cookies in a rack.
class Framework::Response::Cookies def set( params ) @cookies[params.delete( :name )] = params end def remove( params ) @remove_cookies[params.delete( :name )] = params end def commit( headers ) @cookies.each_pair do |name, params| Rack::Utils.set_cookie_header!( headers, name, params ) end @remove_cookies.each_pair do |name, params| Rack::Utils.delete_cookie_header!( headers, name, params ) end end end
Session management class (using Mongo as a backend):
class Database::Mongo::Session < Session def save expire = Time.now + @session_ttl @framework.content.db.find_and_modify( self.collection_name, { :query => { :name => @session_name, :id => @session_id }, :update => { :expire => expire, :name => @session_name, :id => @new_session_id || @session_id , :variables => @variables.to_hash }, :upsert => true }) @framework.response.cookies.set( :name => @session_name, :value => @new_session_id || @session_id, :path => @framework.applications.active.active_request['path'], :domain => @framework.applications.active.active_request['host'], :httponly => true ) end def delete @framework.content.db.remove( self.collection_name, { :id => @session_id } ) @framework.response.cookies.remove( :name => @session_name ) end end
Each time @framework.response.cookies.set is called, it pushes the cookie data into the Framework::Response::Cookies class @cookies .
Before submitting a response, calling Framework::Response::Cookies.commit terminates cookies using Rack::Utils .