Class: Rack::Session::Redic

Inherits:
Abstract::Persisted
  • Object
show all
Defined in:
lib/rack/session/redic.rb

Overview

Rack::Session::Redic provides simple cookie based session management. Session data is stored in Redis via the Redic gem. The corresponding session key is maintained in the cookie.

Options include:

  • :marshaller - You may optionally supply the class/module you would like to use when marshalling objects in and out of Redis. All that is required is that this class respond to the load and dump methods, returning the session hash and a string respectively.
  • :url - Addtionally, you may pass in the URL for your Redis server. The default URL is fetched from the ENV as 'REDIS_URL' in keeping with Heroku and others' practices.
  • :expire_after - Finally, expiration will be passed to the Redis server via the 'EX' option on 'SET'. Expiration should be in seconds, just like Rack's default handling of the :expire_after option. This option will refresh the expiration set in Redis with each request.

Any other options will get passed to Rack::Session::Abstract::Persisted.

Constant Summary collapse

HASH =
{}.freeze
DELETE =

Redis commands.

'DEL'
EX =
'EX'
EXISTS =
'EXISTS'
GET =
'GET'
SET =
'SET'
REDIS_URL =

Assorted.

'REDIS_URL'
ZERO =
0

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, options = HASH) ⇒ Redic

Returns a new instance of Redic.



46
47
48
49
50
51
52
# File 'lib/rack/session/redic.rb', line 46

def initialize(app, options = HASH)
  super(app, options)

  @expires = options[:expire_after]
  @marshaller = options.fetch(:marshaller) { Marshal }
  @storage = ::Redic.new(options.fetch(:url) { ENV.fetch(REDIS_URL) })
end

Instance Attribute Details

#storageRedic (readonly)

Access the storage interface directly. Needed for testing.

Returns:



44
45
46
# File 'lib/rack/session/redic.rb', line 44

def storage
  @storage
end

Instance Method Details

#delete_session(_req, session_id, options) ⇒ Object

Kill the session.



88
89
90
91
92
# File 'lib/rack/session/redic.rb', line 88

def delete_session(_req, session_id, options)
  @storage.call(DELETE, session_id)

  generate_sid unless options[:drop]
end

#find_session(_req, session_id) ⇒ Object

Find the session (or generate a blank one).



69
70
71
72
73
74
75
# File 'lib/rack/session/redic.rb', line 69

def find_session(_req, session_id)
  unless session_id && (session = deserialize(@storage.call(GET, session_id)))
    session_id, session = generate_sid, {} # rubocop:disable Style/ParallelAssignment
  end

  [session_id, session]
end

#generate_sidString

Generate a session ID that doesn't already exist.

Based on Rack::Session::Abstract::Persisted#generate_sid and Rack::Session::Memcache#generate_sid but without the conditional check. We always generate the session ID from SecureRandom#hex.

Returns:

  • (String)


61
62
63
64
65
66
# File 'lib/rack/session/redic.rb', line 61

def generate_sid
  loop do
    session_id = SecureRandom.hex(@sid_length)
    break session_id unless @storage.call(EXISTS, session_id) != ZERO
  end
end

#write_session(_req, session_id, session_data, _options) ⇒ Object

Write the session.



78
79
80
81
82
83
84
85
# File 'lib/rack/session/redic.rb', line 78

def write_session(_req, session_id, session_data, _options)
  arguments = [SET, session_id, serialize(session_data)]
  arguments.push(EX, @expires) if @expires

  @storage.call(*arguments)

  session_id
end