Skip to content

Commit

Permalink
Fallback to the public id when reading the session in the pool adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelfranca authored and tenderlove committed Dec 17, 2019
1 parent 1a532d1 commit 15da2e5
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 4 deletions.
5 changes: 5 additions & 0 deletions lib/rack/session/abstract/id.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@
require 'time'
require 'rack/request'
require 'rack/response'
<<<<<<< HEAD
begin
require 'securerandom'
rescue LoadError
# We just won't get securerandom
end
require "digest/sha2"
=======
require 'securerandom'
require 'digest/sha2'
>>>>>>> Fallback to the public id when reading the session in the pool adapter

module Rack

Expand Down
9 changes: 8 additions & 1 deletion lib/rack/session/pool.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def generate_sid

def get_session(env, sid)
with_lock(env) do
unless sid and session = @pool[sid.private_id]
unless sid and session = get_session_with_fallback(sid)
sid, session = generate_sid, {}
@pool.store sid.private_id, session
end
Expand All @@ -60,6 +60,7 @@ def set_session(env, session_id, new_session, options)

def destroy_session(env, session_id, options)
with_lock(env) do
@pool.delete(session_id.public_id)
@pool.delete(session_id.private_id)
generate_sid unless options[:drop]
end
Expand All @@ -71,6 +72,12 @@ def with_lock(env)
ensure
@mutex.unlock if @mutex.locked?
end

private

def get_session_with_fallback(sid)
@pool[sid.private_id] || @pool[sid.public_id]
end
end
end
end
43 changes: 40 additions & 3 deletions test/spec_session_pool.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

describe Rack::Session::Pool do
session_key = Rack::Session::Pool::DEFAULT_OPTIONS[:key]
session_match = /#{session_key}=[0-9a-fA-F]+;/
session_match = /#{session_key}=([0-9a-fA-F]+);/

incrementor = lambda do |env|
env["rack.session"]["counter"] ||= 0
env["rack.session"]["counter"] += 1
Rack::Response.new(env["rack.session"].inspect).to_a
end

session_id = Rack::Lint.new(lambda do |env|
get_session_id = Rack::Lint.new(lambda do |env|
Rack::Response.new(env["rack.session"].inspect).to_a
end)

Expand Down Expand Up @@ -142,6 +142,43 @@
pool.pool.size.should.equal 1
end

it "can read the session with the legacy id" do
pool = Rack::Session::Pool.new(incrementor)
req = Rack::MockRequest.new(pool)

res0 = req.get("/")
cookie = res0["Set-Cookie"]
session_id = Rack::Session::SessionId.new cookie[session_match, 1]
ses0 = pool.pool[session_id.private_id]
pool.pool[session_id.public_id] = ses0
pool.pool.delete(session_id.private_id)

res1 = req.get("/", "HTTP_COOKIE" => cookie)
res1["Set-Cookie"].must_be_nil
res1.body.must_equal '{"counter"=>2}'
pool.pool[session_id.private_id].wont_be_nil
end

it "drops the session in the legacy id as well" do
pool = Rack::Session::Pool.new(incrementor)
req = Rack::MockRequest.new(pool)
drop = Rack::Utils::Context.new(pool, drop_session)
dreq = Rack::MockRequest.new(drop)

res0 = req.get("/")
cookie = res0["Set-Cookie"]
session_id = Rack::Session::SessionId.new cookie[session_match, 1]
ses0 = pool.pool[session_id.private_id]
pool.pool[session_id.public_id] = ses0
pool.pool.delete(session_id.private_id)

res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
res2["Set-Cookie"].must_be_nil
res2.body.must_equal '{"counter"=>2}'
pool.pool[session_id.private_id].must_be_nil
pool.pool[session_id.public_id].must_be_nil
end

# anyone know how to do this better?
it "should merge sessions when multithreaded" do
unless $DEBUG
Expand Down Expand Up @@ -190,7 +227,7 @@
end

it "does not return a cookie if cookie was not written (only read)" do
app = Rack::Session::Pool.new(session_id)
app = Rack::Session::Pool.new(get_session_id)
res = Rack::MockRequest.new(app).get("/")
res["Set-Cookie"].should.be.nil
end
Expand Down

0 comments on commit 15da2e5

Please sign in to comment.