use a request object in the session middleware

This commit allows us to use one request object rather than allocating
multiple request objects to deal with the session.
This commit is contained in:
Aaron Patterson 2015-08-22 17:57:45 -07:00
parent 4f244f7cab
commit 5fe141638f
8 changed files with 77 additions and 71 deletions

View File

@ -27,7 +27,7 @@ GIT
GIT
remote: git://github.com/rack/rack.git
revision: be777e06bf4de18a7786af1e44647e1498ec1a5d
revision: c94e22401d4719b4d78378c7b63362cd692f9005
specs:
rack (2.0.0.alpha)
json
@ -79,7 +79,7 @@ GIT
GIT
remote: git://github.com/rails/sprockets.git
revision: 653de5268ba862ea23457291824180c67ad5dc99
revision: a61550db7184fc83964fb983547ff09da9efa9be
branch: master
specs:
sprockets (4.0.0)
@ -236,7 +236,7 @@ GEM
resque (~> 1.25)
rufus-scheduler (~> 3.0)
rufus-scheduler (3.1.3)
sass (3.4.16)
sass (3.4.17)
sdoc (0.4.1)
json (~> 1.7, >= 1.7.7)
rdoc (~> 4.0)

View File

@ -314,11 +314,11 @@ module ActionDispatch
end
def session=(session) #:nodoc:
Session.set @env, session
Session.set self, session
end
def session_options=(options)
Session::Options.set @env, options
Session::Options.set self, options
end
# Override Rack's GET method to support indifferent access

View File

@ -274,7 +274,7 @@ module ActionDispatch
req = ActionDispatch::Request.new env
@app.call(env)
ensure
session = Request::Session.find(env) || {}
session = Request::Session.find(req) || {}
flash_hash = req.flash_hash
if flash_hash && (flash_hash.present? || session.key?('flash'))

View File

@ -36,6 +36,11 @@ module ActionDispatch
@default_options.delete(:sidbits)
@default_options.delete(:secure_random)
end
private
def make_request(env)
ActionDispatch::Request.new env
end
end
module StaleSessionCheck
@ -65,8 +70,8 @@ module ActionDispatch
end
module SessionObject # :nodoc:
def prepare_session(env)
Request::Session.create(self, env, @default_options)
def prepare_session(req)
Request::Session.create(self, req, @default_options)
end
def loaded_session?(session)
@ -81,8 +86,7 @@ module ActionDispatch
private
def set_cookie(env, session_id, cookie)
request = ActionDispatch::Request.new(env)
def set_cookie(request, session_id, cookie)
request.cookie_jar[key] = cookie
end
end

View File

@ -71,16 +71,16 @@ module ActionDispatch
super(app, options.merge!(:cookie_only => true))
end
def destroy_session(env, session_id, options)
def destroy_session(req, session_id, options)
new_sid = generate_sid unless options[:drop]
# Reset hash and Assign the new session id
env["action_dispatch.request.unsigned_session_cookie"] = new_sid ? { "session_id" => new_sid } : {}
req.set_header("action_dispatch.request.unsigned_session_cookie", new_sid ? { "session_id" => new_sid } : {})
new_sid
end
def load_session(env)
def load_session(req)
stale_session_check! do
data = unpacked_cookie_data(env)
data = unpacked_cookie_data(req)
data = persistent_session_id!(data)
[data["session_id"], data]
end
@ -88,20 +88,21 @@ module ActionDispatch
private
def extract_session_id(env)
def extract_session_id(req)
stale_session_check! do
unpacked_cookie_data(env)["session_id"]
unpacked_cookie_data(req)["session_id"]
end
end
def unpacked_cookie_data(env)
env["action_dispatch.request.unsigned_session_cookie"] ||= begin
stale_session_check! do
if data = get_cookie(env)
def unpacked_cookie_data(req)
req.get_header("action_dispatch.request.unsigned_session_cookie") do |k|
v = stale_session_check! do
if data = get_cookie(req)
data.stringify_keys!
end
data || {}
end
req.set_header k, v
end
end
@ -111,21 +112,20 @@ module ActionDispatch
data
end
def set_session(env, sid, session_data, options)
def set_session(req, sid, session_data, options)
session_data["session_id"] = sid
session_data
end
def set_cookie(env, session_id, cookie)
cookie_jar(env)[@key] = cookie
def set_cookie(request, session_id, cookie)
cookie_jar(request)[@key] = cookie
end
def get_cookie(env)
cookie_jar(env)[@key]
def get_cookie(req)
cookie_jar(req)[@key]
end
def cookie_jar(env)
request = ActionDispatch::Request.new(env)
def cookie_jar(request)
request.cookie_jar.signed_or_encrypted
end
end

View File

@ -11,31 +11,31 @@ module ActionDispatch
Unspecified = Object.new
# Creates a session hash, merging the properties of the previous session if any
def self.create(store, env, default_options)
session_was = find env
session = Request::Session.new(store, env)
def self.create(store, req, default_options)
session_was = find req
session = Request::Session.new(store, req)
session.merge! session_was if session_was
set(env, session)
Options.set(env, Request::Session::Options.new(store, default_options))
set(req, session)
Options.set(req, Request::Session::Options.new(store, default_options))
session
end
def self.find(env)
env[ENV_SESSION_KEY]
def self.find(req)
req.get_header ENV_SESSION_KEY
end
def self.set(env, session)
env[ENV_SESSION_KEY] = session
def self.set(req, session)
req.set_header ENV_SESSION_KEY, session
end
class Options #:nodoc:
def self.set(env, options)
env[ENV_SESSION_OPTIONS_KEY] = options
def self.set(req, options)
req.set_header ENV_SESSION_OPTIONS_KEY, options
end
def self.find(env)
env[ENV_SESSION_OPTIONS_KEY]
def self.find(req)
req.get_header ENV_SESSION_OPTIONS_KEY
end
def initialize(by, default_options)
@ -47,9 +47,9 @@ module ActionDispatch
@delegate[key]
end
def id(env)
def id(req)
@delegate.fetch(:id) {
@by.send(:extract_session_id, env)
@by.send(:extract_session_id, req)
}
end
@ -58,26 +58,26 @@ module ActionDispatch
def values_at(*args); @delegate.values_at(*args); end
end
def initialize(by, env)
def initialize(by, req)
@by = by
@env = env
@req = req
@delegate = {}
@loaded = false
@exists = nil # we haven't checked yet
end
def id
options.id(@env)
options.id(@req)
end
def options
Options.find @env
Options.find @req
end
def destroy
clear
options = self.options || {}
@by.send(:destroy_session, @env, options.id(@env), options)
@by.send(:destroy_session, @req, options.id(@req), options)
# Load the new sid to be written with the response
@loaded = false
@ -181,7 +181,7 @@ module ActionDispatch
def exists?
return @exists unless @exists.nil?
@exists = @by.send(:session_exists?, @env)
@exists = @by.send(:session_exists?, @req)
end
def loaded?
@ -209,7 +209,7 @@ module ActionDispatch
end
def load!
id, session = @by.load_session @env
id, session = @by.load_session @req
options[:id] = id
@delegate.replace(stringify_keys(session))
@loaded = true

View File

@ -4,40 +4,42 @@ require 'action_dispatch/middleware/session/abstract_store'
module ActionDispatch
class Request
class SessionTest < ActiveSupport::TestCase
attr_reader :req
def setup
@req = ActionDispatch::Request.new({})
end
def test_create_adds_itself_to_env
env = {}
s = Session.create(store, env, {})
assert_equal s, env[Rack::RACK_SESSION]
s = Session.create(store, req, {})
assert_equal s, req.env[Rack::RACK_SESSION]
end
def test_to_hash
env = {}
s = Session.create(store, env, {})
s = Session.create(store, req, {})
s['foo'] = 'bar'
assert_equal 'bar', s['foo']
assert_equal({'foo' => 'bar'}, s.to_hash)
end
def test_create_merges_old
env = {}
s = Session.create(store, env, {})
s = Session.create(store, req, {})
s['foo'] = 'bar'
s1 = Session.create(store, env, {})
s1 = Session.create(store, req, {})
assert_not_equal s, s1
assert_equal 'bar', s1['foo']
end
def test_find
env = {}
assert_nil Session.find(env)
assert_nil Session.find(req)
s = Session.create(store, env, {})
assert_equal s, Session.find(env)
s = Session.create(store, req, {})
assert_equal s, Session.find(req)
end
def test_destroy
s = Session.create(store, {}, {})
s = Session.create(store, req, {})
s['rails'] = 'ftw'
s.destroy
@ -46,21 +48,21 @@ module ActionDispatch
end
def test_keys
s = Session.create(store, {}, {})
s = Session.create(store, req, {})
s['rails'] = 'ftw'
s['adequate'] = 'awesome'
assert_equal %w[rails adequate], s.keys
end
def test_values
s = Session.create(store, {}, {})
s = Session.create(store, req, {})
s['rails'] = 'ftw'
s['adequate'] = 'awesome'
assert_equal %w[ftw awesome], s.values
end
def test_clear
s = Session.create(store, {}, {})
s = Session.create(store, req, {})
s['rails'] = 'ftw'
s['adequate'] = 'awesome'
@ -69,7 +71,7 @@ module ActionDispatch
end
def test_update
s = Session.create(store, {}, {})
s = Session.create(store, req, {})
s['rails'] = 'ftw'
s.update(:rails => 'awesome')
@ -79,7 +81,7 @@ module ActionDispatch
end
def test_delete
s = Session.create(store, {}, {})
s = Session.create(store, req, {})
s['rails'] = 'ftw'
s.delete('rails')
@ -88,7 +90,7 @@ module ActionDispatch
end
def test_fetch
session = Session.create(store, {}, {})
session = Session.create(store, req, {})
session['one'] = '1'
assert_equal '1', session.fetch(:one)

View File

@ -27,7 +27,7 @@ module ActionDispatch
as.call(env)
assert @env
assert Request::Session.find @env
assert Request::Session.find ActionDispatch::Request.new @env
end
def test_new_session_object_is_merged_with_old
@ -36,11 +36,11 @@ module ActionDispatch
as.call(env)
assert @env
session = Request::Session.find @env
session = Request::Session.find ActionDispatch::Request.new @env
session['foo'] = 'bar'
as.call(@env)
session1 = Request::Session.find @env
session1 = Request::Session.find ActionDispatch::Request.new @env
assert_not_equal session, session1
assert_equal session.to_hash, session1.to_hash