Skip to content

Commit 9ef8469

Browse files
committed
Do not return new cookies when session isn’t changed
1 parent 4eb9ea8 commit 9ef8469

File tree

4 files changed

+31
-5
lines changed

4 files changed

+31
-5
lines changed

lib/rack/session/abstract/id.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ def cookie_value(data)
419419

420420
# Sets the cookie back to the client with session id. We skip the cookie
421421
# setting if the value didn't change (sid is the same) or expires was given.
422+
# Allow subclasses to set the cookie value in a different way.
422423

423424
def set_cookie(request, response, cookie)
424425
if request.cookies[@key] != cookie[:value] || cookie[:expires]

lib/rack/session/constants.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
module Rack
88
module Session
99
RACK_SESSION = 'rack.session'
10+
RACK_SESSION_WAS = 'rack.session.was'
1011
RACK_SESSION_OPTIONS = 'rack.session.options'
1112
RACK_SESSION_UNPACKED_COOKIE_DATA = 'rack.session.unpacked_cookie_data'
1213
end

lib/rack/session/cookie.rb

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,13 @@ def unpacked_cookie_data(request)
243243
end
244244
end
245245

246-
request.set_header(k, session_data || {})
246+
if session_data
247+
request.set_header(RACK_SESSION_WAS, session_data.dup)
248+
request.set_header(k, session_data)
249+
else
250+
request.set_header(RACK_SESSION_WAS, nil)
251+
request.set_header(k, {})
252+
end
247253
end
248254
end
249255

@@ -253,6 +259,14 @@ def persistent_session_id!(data, sid = nil)
253259
data
254260
end
255261

262+
def set_cookie(request, response, cookie)
263+
return if request.session.to_h == request.get_header(RACK_SESSION_WAS).to_h &&
264+
!request.get_header(RACK_SESSION_OPTIONS).fetch(:renew, false) &&
265+
!cookie[:expires]
266+
267+
response.set_cookie(@key, cookie)
268+
end
269+
256270
class SessionId < DelegateClass(Session::SessionId)
257271
attr_reader :cookie_value
258272

test/spec_session_cookie.rb

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,15 @@ def decode(str); @calls << :decode; JSON.parse(str); end
227227
response["Set-Cookie"].must_match /SameSite=None/i
228228
end
229229

230+
it "does not create new cookies if cookies does not change" do
231+
response = response_for(app: incrementor)
232+
cookie = response["Set-Cookie"]
233+
cookie.must_include "rack.session="
234+
response = response_for(app: only_session_id, cookie: cookie)
235+
cookie = response["Set-Cookie"]
236+
cookie.must_be_nil
237+
end
238+
230239
it "allows using a lambda to specify same_site option, because some browsers require different settings" do
231240
# Details of why this might need to be set dynamically:
232241
# https://www.chromium.org/updates/same-site/incompatible-clients
@@ -253,14 +262,16 @@ def decode(str); @calls << :decode; JSON.parse(str); end
253262
response = response_for(app: incrementor)
254263
cookie = response['Set-Cookie']
255264
response = response_for(app: only_session_id, cookie: cookie)
256-
cookie = response['Set-Cookie'] if response['Set-Cookie']
265+
response['Set-Cookie'].must_be_nil
257266

258267
response.body.wont_equal ""
259268
old_session_id = response.body
260269

261270
response = response_for(app: renewer, cookie: cookie)
262-
cookie = response['Set-Cookie'] if response['Set-Cookie']
263-
response = response_for(app: only_session_id, cookie: cookie)
271+
new_cookie = response['Set-Cookie']
272+
new_cookie.wont_equal cookie
273+
274+
response = response_for(app: only_session_id, cookie: new_cookie)
264275

265276
response.body.wont_equal ""
266277
response.body.wont_equal old_session_id
@@ -276,7 +287,6 @@ def decode(str); @calls << :decode; JSON.parse(str); end
276287
response = response_for(app: destroy_session, cookie: response)
277288
response = response_for(app: only_session_id, cookie: response)
278289

279-
response.body.wont_equal ""
280290
response.body.wont_equal old_session_id
281291
end
282292

0 commit comments

Comments
 (0)