summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Mendonça França <rafael@franca.dev>2019-10-09 19:14:08 -0400
committerAaron Patterson <aaron.patterson@gmail.com>2019-12-17 09:54:34 -0800
commit1e96e0f197777458216bb3dfdbcce57a0bbba0c5 (patch)
treec8884736639f08f269bc6b77a2795bb476852ae4
parent3ba123d278f1085ba78fc000df954e507af2d622 (diff)
downloadrack-1e96e0f197777458216bb3dfdbcce57a0bbba0c5.tar.gz
Fallback to the public id when reading the session in the pool adapter
-rw-r--r--lib/rack/session/abstract/id.rb1
-rw-r--r--lib/rack/session/pool.rb9
-rw-r--r--test/spec_session_pool.rb43
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