55# See the file LICENSE.txt for details.
66#++
77
8- require 'rack/session/abstract/id' unless defined? ( ::Rack ::Session ::Abstract ::ID )
8+ require 'rack/session/abstract/id' unless defined? ( ::Rack ::Session ::Abstract ::Persisted )
99
1010module JRuby ::Rack
1111 module Session
@@ -28,7 +28,7 @@ def method_missing(method, *args, &block)
2828 end
2929
3030 # Rack based SessionStore implementation but compatible with (older) AbstractStore.
31- class SessionStore < ::Rack ::Session ::Abstract ::ID
31+ class SessionStore < ::Rack ::Session ::Abstract ::Persisted
3232
3333 ENV_SERVLET_SESSION_KEY = 'java.servlet_session' . freeze
3434 RAILS_SESSION_KEY = "__current_rails_session" . freeze
@@ -37,13 +37,6 @@ def initialize(app, options={})
3737 super ( app , options . merge! ( :cookie_only => false , :defer => true ) )
3838 end
3939
40- def context ( env , app = @app )
41- req = make_request env
42- prepare_session ( req )
43- status , headers , body = app . call ( req . env )
44- commit_session ( req , status , headers , body )
45- end
46-
4740 # (public) servlet specific methods :
4841
4942 def get_servlet_session ( env , create = false )
@@ -69,7 +62,7 @@ def get_servlet_session(env, create = false)
6962 servlet_session
7063 end
7164
72- private # Rack::Session::Abstract::ID overrides :
65+ private # Rack::Session::Abstract::Persisted overrides :
7366
7467 def session_class
7568 ::JRuby ::Rack ::Session ::SessionHash
@@ -83,6 +76,7 @@ def generate_sid(secure = @sid_secure)
8376 nil # dummy method - no session id generation with servlet API
8477 end
8578
79+ # Alternative to overriding find_session(req)
8680 def load_session ( req ) # session_id arg for get_session alias
8781 session_id , session = false , { }
8882 if servlet_session = get_servlet_session ( req . env )
@@ -122,40 +116,51 @@ def loaded_session?(session)
122116 ! session . is_a? ( ::JRuby ::Rack ::Session ::SessionHash ) || session . loaded?
123117 end
124118
125- def commit_session ( req , status , headers , body )
126- session = req . env [ ::Rack ::RACK_SESSION ]
127- options = req . env [ ::Rack ::RACK_SESSION_OPTIONS ]
119+ # Overridden from Rack, removing support for deferral and unnecessary cookie support when using Java Servlet sessions.
120+ def commit_session ( req , _res )
121+ session = req . get_header ::Rack ::RACK_SESSION
122+ options = session . options
128123
129124 if options [ :drop ] || options [ :renew ]
130- destroy_session ( req . env , options [ :id ] , options )
125+ delete_session ( req , session . id , options )
131126 end
132127
133- return [ status , headers , body ] if options [ :drop ] || options [ :skip ]
128+ return if options [ :drop ] || options [ :skip ]
134129
135130 if loaded_session? ( session )
136- session_id = session . respond_to? ( :id= ) ? session . id : options [ :id ]
137- session_data = session . to_hash . delete_if { |_ , v | v . nil? }
138- unless set_session ( req . env , session_id , session_data , options )
139- req . env [ "rack.errors" ] . puts ( "WARNING #{ self . class . name } failed to save session. Content dropped." )
131+ # Mirror behaviour of Rails ActionDispatch::Session::AbstractStore#commit_session for Rails 7.1+ compatibility
132+ commit_csrf_token ( req , session )
133+
134+ session_id ||= session . id
135+ session_data = session . to_hash . delete_if { |k , v | v . nil? }
136+
137+ unless write_session ( req , session_id , session_data , options )
138+ req . get_header ( ::Rack ::RACK_ERRORS ) . puts ( "Warning! #{ self . class . name } failed to save session. Content dropped." )
140139 end
141140 end
141+ end
142142
143- [ status , headers , body ]
143+ def commit_csrf_token ( req , session_hash )
144+ csrf_token = req . env [ ::ActionController ::RequestForgeryProtection ::CSRF_TOKEN ] if defined? ( ::ActionController ::RequestForgeryProtection ::CSRF_TOKEN )
145+ if csrf_token
146+ session_hash [ :_csrf_token ] = csrf_token
147+ end
144148 end
145149
146- def set_session ( env , session_id , hash , options )
147- if session_id . nil? && hash . empty?
148- destroy_session ( env )
150+ def write_session ( req , session_id , session_hash , _options )
151+ if session_id . nil? && session_hash . empty?
152+ delete_session ( req )
149153 return true
150154 end
151- if servlet_session = get_servlet_session ( env , true )
155+
156+ if servlet_session = get_servlet_session ( req . env , true )
152157 begin
153158 servlet_session . synchronized do
154159 keys = servlet_session . getAttributeNames
155- keys . select { |key | ! hash . has_key? ( key ) } . each do |key |
160+ keys . select { |key | ! session_hash . has_key? ( key ) } . each do |key |
156161 servlet_session . removeAttribute ( key )
157162 end
158- hash . delete_if do |key , value |
163+ session_hash . delete_if do |key , value |
159164 if String === key
160165 case value
161166 when String , Numeric , true , false , nil
@@ -171,8 +176,8 @@ def set_session(env, session_id, hash, options)
171176 end
172177 end
173178 end
174- if ! hash . empty?
175- marshalled_string = Marshal . dump ( hash )
179+ if ! session_hash . empty?
180+ marshalled_string = Marshal . dump ( session_hash )
176181 marshalled_bytes = marshalled_string . to_java_bytes
177182 servlet_session . setAttribute ( RAILS_SESSION_KEY , marshalled_bytes )
178183 elsif servlet_session . getAttribute ( RAILS_SESSION_KEY )
@@ -188,9 +193,9 @@ def set_session(env, session_id, hash, options)
188193 end
189194 end
190195
191- def destroy_session ( env , session_id = nil , options = nil )
192- # session_id and options arg defaults for destory alias
193- ( session = get_servlet_session ( env ) ) && session . synchronized { session . invalidate }
196+ def delete_session ( req , _session_id = nil , _options = nil )
197+ # session_id and options arg defaults for delete alias
198+ ( session = get_servlet_session ( req . env ) ) && session . synchronized { session . invalidate }
194199 rescue java . lang . IllegalStateException # if session already invalid
195200 nil
196201 end
0 commit comments