Class: Rack::Session::Abstract::Persisted

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/session/abstract/id.rb

Overview

ID sets up a basic framework for implementing an id based sessioning service. Cookies sent to the client for maintaining sessions will only contain an id reference. Only #find_session, #write_session and #delete_session are required to be overwritten.

All parameters are optional.

  • :key determines the name of the cookie, by default it is 'rack.session'

  • :path, :domain, :expire_after, :secure, and :httponly set the related cookie options as by Rack::Response#set_cookie

  • :skip will not a set a cookie in the response nor update the session state

  • :defer will not set a cookie in the response but still update the session state if it is used with a backend

  • :renew (implementation dependent) will prompt the generation of a new session id, and migration of data to be referenced at the new id. If :defer is set, it will be overridden and the cookie will be set.

  • :sidbits sets the number of bits in length that a generated session id will be.

These options can be set on a per request basis, at the location of env['rack.session.options']. Additionally the id of the session can be found within the options hash at the key :id. It is highly not recommended to change its value.

Is Rack::Utils::Context compatible.

Not included by default; you must require 'rack/session/abstract/id' to use.

Direct Known Subclasses

ID, PersistedSecure

Constant Summary collapse

DEFAULT_OPTIONS =
{
  key: RACK_SESSION,
  path: '/',
  domain: nil,
  expire_after: nil,
  secure: false,
  httponly: true,
  defer: false,
  renew: false,
  sidbits: 128,
  cookie_only: true,
  secure_random: ::SecureRandom
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ Persisted

Returns a new instance of Persisted.


250
251
252
253
254
255
256
257
# File 'lib/rack/session/abstract/id.rb', line 250

def initialize(app, options = {})
  @app = app
  @default_options = self.class::DEFAULT_OPTIONS.merge(options)
  @key = @default_options.delete(:key)
  @cookie_only = @default_options.delete(:cookie_only)
  @same_site = @default_options.delete(:same_site)
  initialize_sid
end

Instance Attribute Details

#default_optionsObject (readonly)

Returns the value of attribute default_options


248
249
250
# File 'lib/rack/session/abstract/id.rb', line 248

def default_options
  @default_options
end

#keyObject (readonly)

Returns the value of attribute key


248
249
250
# File 'lib/rack/session/abstract/id.rb', line 248

def key
  @key
end

#sid_secureObject (readonly)

Returns the value of attribute sid_secure


248
249
250
# File 'lib/rack/session/abstract/id.rb', line 248

def sid_secure
  @sid_secure
end

Instance Method Details

#call(env) ⇒ Object


259
260
261
# File 'lib/rack/session/abstract/id.rb', line 259

def call(env)
  context(env)
end

#commit_session(req, res) ⇒ Object

Acquires the session from the environment and the session id from the session options and passes them to #write_session. If successful and the :defer option is not true, a cookie will be added to the response with the session's id.


373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
# File 'lib/rack/session/abstract/id.rb', line 373

def commit_session(req, res)
  session = req.get_header RACK_SESSION
  options = session.options

  if options[:drop] || options[:renew]
    session_id = delete_session(req, session.id || generate_sid, options)
    return unless session_id
  end

  return unless commit_session?(req, session, options)

  session.send(:load!) unless loaded_session?(session)
  session_id ||= session.id
  session_data = session.to_hash.delete_if { |k, v| v.nil? }

  if not data = write_session(req, session_id, session_data, options)
    req.get_header(RACK_ERRORS).puts("Warning! #{self.class.name} failed to save session. Content dropped.")
  elsif options[:defer] and not options[:renew]
    req.get_header(RACK_ERRORS).puts("Deferring cookie for #{session_id}") if $VERBOSE
  else
    cookie = Hash.new
    cookie[:value] = cookie_value(data)
    cookie[:expires] = Time.now + options[:expire_after] if options[:expire_after]
    cookie[:expires] = Time.now + options[:max_age] if options[:max_age]

    if @same_site.respond_to? :call
      cookie[:same_site] = @same_site.call(req, res)
    else
      cookie[:same_site] = @same_site
    end
    set_cookie(req, res, cookie.merge!(options))
  end
end

#context(env, app = @app) ⇒ Object


263
264
265
266
267
268
269
270
# File 'lib/rack/session/abstract/id.rb', line 263

def context(env, app = @app)
  req = make_request env
  prepare_session(req)
  status, headers, body = app.call(req.env)
  res = Rack::Response::Raw.new status, headers
  commit_session(req, res)
  [status, headers, body]
end