class Rack::Session::Abstract::Persisted
def call(env)
def call(env) context(env) end
def commit_session(req, res)
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
def commit_session?(req, session, options)
def commit_session?(req, session, options) if options[:skip] false else has_session = loaded_session?(session) || forced_session_update?(session, options) has_session && security_matches?(req, options) end end
def context(env, app = @app)
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
def cookie_value(data)
def cookie_value(data) data end
def current_session_id(req)
def current_session_id(req) req.get_header(RACK_SESSION).id end
def delete_session(req, sid, options)
def delete_session(req, sid, options) raise '#delete_session not implemented' end
def extract_session_id(request)
def extract_session_id(request) sid = request.cookies[@key] sid ||= request.params[@key] unless @cookie_only sid end
def find_session(env, sid)
def find_session(env, sid) raise '#find_session not implemented.' end
def force_options?(options)
def force_options?(options) options.values_at(:max_age, :renew, :drop, :defer, :expire_after).any? end
def forced_session_update?(session, options)
def forced_session_update?(session, options) force_options?(options) && session && !session.empty? end
def generate_sid(secure = @sid_secure)
def generate_sid(secure = @sid_secure) if secure secure.hex(@sid_length) else "%0#{@sid_length}x" % Kernel.rand(2**@sidbits - 1) end rescue NotImplementedError generate_sid(false) end
def initialize(app, options = {})
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
def initialize_sid
def initialize_sid @sidbits = @default_options[:sidbits] @sid_secure = @default_options[:secure_random] @sid_length = @sidbits / 4 end
def load_session(req)
def load_session(req) sid = current_session_id(req) sid, session = find_session(req, sid) [sid, session || {}] end
def loaded_session?(session)
def loaded_session?(session) !session.is_a?(session_class) || session.loaded? end
def make_request(env)
def make_request(env) Rack::Request.new env end
def prepare_session(req)
def prepare_session(req) session_was = req.get_header RACK_SESSION session = session_class.new(self, req) req.set_header RACK_SESSION, session req.set_header RACK_SESSION_OPTIONS, @default_options.dup session.merge! session_was if session_was end
def security_matches?(request, options)
def security_matches?(request, options) return true unless options[:secure] request.ssl? end
def session_class
def session_class SessionHash end
def session_exists?(req)
def session_exists?(req) value = current_session_id(req) value && !value.empty? end
def set_cookie(request, res, cookie)
def set_cookie(request, res, cookie) if request.cookies[@key] != cookie[:value] || cookie[:expires] res.set_cookie_header = Utils.add_cookie_to_header(res.set_cookie_header, @key, cookie) end end
def write_session(req, sid, session, options)
def write_session(req, sid, session, options) raise '#write_session not implemented.' end