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

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 = {}) ⇒ Redic

Returns a new instance of Redic.



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

def initialize(app, options = {})
  super

  @expires = options[:expire_after]
  @marshaller = options.fetch(:marshaller) { Marshal }
  @mutex = Mutex.new
  @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:



42
43
44
# File 'lib/rack/session/redic.rb', line 42

def storage
  @storage
end

Instance Method Details

#delete_session(_req, session_id, options) ⇒ Object

Kill the session.



91
92
93
94
95
96
# File 'lib/rack/session/redic.rb', line 91

def delete_session(_req, session_id, options)
  @mutex.synchronize do
    @storage.call(DELETE, session_id)
    generate_sid unless options[:drop]
  end
end

#find_session(_req, session_id) ⇒ Object

Find the session (or generate a blank one).



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

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

    [session_id, session]
  end
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)


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

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, new_session, _options) ⇒ Object

Write the session.



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

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

  @mutex.synchronize do
    @storage.call(*arguments)

    session_id
  end
end