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 3ba123d commit 1e96e0f
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 4 deletions.
1 change: 1 addition & 0 deletions lib/rack/session/abstract/id.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require 'rack/request'
require 'rack/response'
require 'securerandom'
require 'digest/sha2'

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 find_session(req, sid)
with_lock(req) 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 write_session(req, session_id, new_session, options)

def delete_session(req, session_id, options)
with_lock(req) 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(req)
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 @@ -6,15 +6,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 @@ -143,6 +143,43 @@
pool.pool.size.must_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 @@ -191,7 +228,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"].must_be_nil
end
Expand Down

0 comments on commit 1e96e0f

Please sign in to comment.