diff options
author | Rafael Mendonça França <rafael@franca.dev> | 2019-10-09 19:14:08 -0400 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2019-12-17 09:54:34 -0800 |
commit | 1e96e0f197777458216bb3dfdbcce57a0bbba0c5 (patch) | |
tree | c8884736639f08f269bc6b77a2795bb476852ae4 | |
parent | 3ba123d278f1085ba78fc000df954e507af2d622 (diff) | |
download | rack-1e96e0f197777458216bb3dfdbcce57a0bbba0c5.tar.gz |
Fallback to the public id when reading the session in the pool adapter
-rw-r--r-- | lib/rack/session/abstract/id.rb | 1 | ||||
-rw-r--r-- | lib/rack/session/pool.rb | 9 | ||||
-rw-r--r-- | test/spec_session_pool.rb | 43 |
3 files changed, 49 insertions, 4 deletions
diff --git a/lib/rack/session/abstract/id.rb b/lib/rack/session/abstract/id.rb index e4f7fd03..7a88429e 100644 --- a/lib/rack/session/abstract/id.rb +++ b/lib/rack/session/abstract/id.rb @@ -6,6 +6,7 @@ require 'time' require 'rack/request' require 'rack/response' require 'securerandom' +require 'digest/sha2' module Rack diff --git a/lib/rack/session/pool.rb b/lib/rack/session/pool.rb index 017fec45..36e7cde2 100644 --- a/lib/rack/session/pool.rb +++ b/lib/rack/session/pool.rb @@ -43,7 +43,7 @@ module Rack 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 @@ -60,6 +60,7 @@ module Rack 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 @@ -71,6 +72,12 @@ module Rack 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 diff --git a/test/spec_session_pool.rb b/test/spec_session_pool.rb index 2d061691..62a0505e 100644 --- a/test/spec_session_pool.rb +++ b/test/spec_session_pool.rb @@ -6,7 +6,7 @@ require 'rack/session/pool' 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 @@ -14,7 +14,7 @@ describe Rack::Session::Pool do 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) @@ -143,6 +143,43 @@ describe Rack::Session::Pool do 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 @@ -191,7 +228,7 @@ describe Rack::Session::Pool do 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 |