diff options
Diffstat (limited to 'actionpack/lib')
4 files changed, 171 insertions, 153 deletions
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index 796e0dbc45..9748956052 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -6,6 +6,7 @@ require 'active_support/core_ext/hash/indifferent_access' require 'active_support/core_ext/string/access' require 'active_support/inflector' require 'action_dispatch/http/headers' +require 'action_dispatch/request/session' require 'action_controller/metal/exceptions' module ActionDispatch @@ -220,11 +221,11 @@ module ActionDispatch end def session=(session) #:nodoc: - @env['rack.session'] = session + Session.set @env, session end def session_options=(options) - @env['rack.session.options'] = options + Session::Options.set @env, options end # Override Rack's GET method to support indifferent access diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb index fd0ce62a3b..bc68615be7 100644 --- a/actionpack/lib/action_dispatch/middleware/flash.rb +++ b/actionpack/lib/action_dispatch/middleware/flash.rb @@ -218,7 +218,7 @@ module ActionDispatch def call(env) @app.call(env) ensure - session = env['rack.session'] || {} + session = Request::Session.find(env) || {} flash_hash = env[KEY] if flash_hash diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 134ca2dc5f..d902adaff1 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -2,6 +2,7 @@ require 'rack/utils' require 'rack/request' require 'rack/session/abstract/id' require 'action_dispatch/middleware/cookies' +require 'action_dispatch/request/session' require 'active_support/core_ext/object/blank' module ActionDispatch @@ -84,154 +85,4 @@ module ActionDispatch end end end - - class Request - # SessionHash is responsible to lazily load the session from store. - class Session # :nodoc: - ENV_SESSION_KEY = Rack::Session::Abstract::ENV_SESSION_KEY # :nodoc: - ENV_SESSION_OPTIONS_KEY = Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY # :nodoc: - - def self.create(store, env, default_options) - session_was = env[ENV_SESSION_KEY] - session = Request::Session.new(store, env) - env[ENV_SESSION_KEY] = session - env[ENV_SESSION_OPTIONS_KEY] = Request::Session::Options.new(store, env, default_options) - env[ENV_SESSION_KEY].merge! session_was if session_was - session - end - - def self.find(env) - env[ENV_SESSION_KEY] - end - - class Options #:nodoc: - def initialize(by, env, default_options) - @by = by - @env = env - @delegate = default_options - end - - def [](key) - if key == :id - @delegate.fetch(key) { - @delegate[:id] = @by.send(:extract_session_id, @env) - } - else - @delegate[key] - end - end - - def []=(k,v); @delegate[k] = v; end - def to_hash; @delegate.dup; end - def values_at(*args); @delegate.values_at(*args); end - end - - def initialize(by, env) - @by = by - @env = env - @delegate = {} - @loaded = false - @exists = nil # we haven't checked yet - end - - def options - @env[ENV_SESSION_OPTIONS_KEY] - end - - def destroy - clear - options = self.options || {} - @by.send(:destroy_session, @env, options[:id], options) - options[:id] = nil - @loaded = false - end - - def [](key) - load_for_read! - @delegate[key.to_s] - end - - def has_key?(key) - load_for_read! - @delegate.key?(key.to_s) - end - alias :key? :has_key? - alias :include? :has_key? - - def []=(key, value) - load_for_write! - @delegate[key.to_s] = value - end - - def clear - load_for_write! - @delegate.clear - end - - def to_hash - load_for_read! - @delegate.dup.delete_if { |_,v| v.nil? } - end - - def update(hash) - load_for_write! - @delegate.update stringify_keys(hash) - end - - def delete(key) - load_for_write! - @delegate.delete key.to_s - end - - def inspect - if loaded? - super - else - "#<#{self.class}:0x#{(object_id << 1).to_s(16)} not yet loaded>" - end - end - - def exists? - return @exists unless @exists.nil? - @exists = @by.send(:session_exists?, @env) - end - - def loaded? - @loaded - end - - def empty? - load_for_read! - @delegate.empty? - end - - def merge!(other) - load_for_write! - @delegate.merge!(other) - end - - private - - def load_for_read! - load! if !loaded? && exists? - end - - def load_for_write! - load! unless loaded? - end - - def load! - id, session = @by.load_session @env - options[:id] = id - @delegate.replace(stringify_keys(session)) - @loaded = true - end - - def stringify_keys(other) - other.each_with_object({}) { |(key, value), hash| - hash[key.to_s] = value - } - end - end - end end diff --git a/actionpack/lib/action_dispatch/request/session.rb b/actionpack/lib/action_dispatch/request/session.rb new file mode 100644 index 0000000000..338165935b --- /dev/null +++ b/actionpack/lib/action_dispatch/request/session.rb @@ -0,0 +1,166 @@ +require 'rack/session/abstract/id' + +module ActionDispatch + class Request < Rack::Request + # SessionHash is responsible to lazily load the session from store. + class Session # :nodoc: + ENV_SESSION_KEY = Rack::Session::Abstract::ENV_SESSION_KEY # :nodoc: + ENV_SESSION_OPTIONS_KEY = Rack::Session::Abstract::ENV_SESSION_OPTIONS_KEY # :nodoc: + + def self.create(store, env, default_options) + session_was = find env + session = Request::Session.new(store, env) + session.merge! session_was if session_was + + set(env, session) + Options.set(env, Request::Session::Options.new(store, env, default_options)) + session + end + + def self.find(env) + env[ENV_SESSION_KEY] + end + + def self.set(env, session) + env[ENV_SESSION_KEY] = session + end + + class Options #:nodoc: + def self.set(env, options) + env[ENV_SESSION_OPTIONS_KEY] = options + end + + def self.find(env) + env[ENV_SESSION_OPTIONS_KEY] + end + + def initialize(by, env, default_options) + @by = by + @env = env + @delegate = default_options + end + + def [](key) + if key == :id + @delegate.fetch(key) { + @delegate[:id] = @by.send(:extract_session_id, @env) + } + else + @delegate[key] + end + end + + def []=(k,v); @delegate[k] = v; end + def to_hash; @delegate.dup; end + def values_at(*args); @delegate.values_at(*args); end + end + + def initialize(by, env) + @by = by + @env = env + @delegate = {} + @loaded = false + @exists = nil # we haven't checked yet + end + + def options + Options.find @env + end + + def destroy + clear + options = self.options || {} + @by.send(:destroy_session, @env, options[:id], options) + options[:id] = nil + @loaded = false + end + + def [](key) + load_for_read! + @delegate[key.to_s] + end + + def has_key?(key) + load_for_read! + @delegate.key?(key.to_s) + end + alias :key? :has_key? + alias :include? :has_key? + + def []=(key, value) + load_for_write! + @delegate[key.to_s] = value + end + + def clear + load_for_write! + @delegate.clear + end + + def to_hash + load_for_read! + @delegate.dup.delete_if { |_,v| v.nil? } + end + + def update(hash) + load_for_write! + @delegate.update stringify_keys(hash) + end + + def delete(key) + load_for_write! + @delegate.delete key.to_s + end + + def inspect + if loaded? + super + else + "#<#{self.class}:0x#{(object_id << 1).to_s(16)} not yet loaded>" + end + end + + def exists? + return @exists unless @exists.nil? + @exists = @by.send(:session_exists?, @env) + end + + def loaded? + @loaded + end + + def empty? + load_for_read! + @delegate.empty? + end + + def merge!(other) + load_for_write! + @delegate.merge!(other) + end + + private + + def load_for_read! + load! if !loaded? && exists? + end + + def load_for_write! + load! unless loaded? + end + + def load! + id, session = @by.load_session @env + options[:id] = id + @delegate.replace(stringify_keys(session)) + @loaded = true + end + + def stringify_keys(other) + other.each_with_object({}) { |(key, value), hash| + hash[key.to_s] = value + } + end + end + end +end |