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, :httponly, :partitioned and :same_site 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,
  partitioned: false,
  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.



257
258
259
260
261
262
263
264
265
# File 'lib/rack/session/abstract/id.rb', line 257

def initialize(app, options = {})
  @app = app
  @default_options = self.class::DEFAULT_OPTIONS.merge(options)
  @key = @default_options.delete(:key)
  @assume_ssl = @default_options.delete(:assume_ssl)
  @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.



255
256
257
# File 'lib/rack/session/abstract/id.rb', line 255

def default_options
  @default_options
end

#keyObject (readonly)

Returns the value of attribute key.



255
256
257
# File 'lib/rack/session/abstract/id.rb', line 255

def key
  @key
end

#same_siteObject (readonly)

Returns the value of attribute same_site.



255
256
257
# File 'lib/rack/session/abstract/id.rb', line 255

def same_site
  @same_site
end

#sid_secureObject (readonly)

Returns the value of attribute sid_secure.



255
256
257
# File 'lib/rack/session/abstract/id.rb', line 255

def sid_secure
  @sid_secure
end

Instance Method Details

#call(env) ⇒ Object



267
268
269
# File 'lib/rack/session/abstract/id.rb', line 267

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.



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
406
407
408
409
410
411
412
413
# File 'lib/rack/session/abstract/id.rb', line 381

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



271
272
273
274
275
276
277
278
# File 'lib/rack/session/abstract/id.rb', line 271

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