rack 1.6.13 → 2.0.0.alpha

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack might be problematic. Click here for more details.

Files changed (138) hide show
  1. checksums.yaml +5 -5
  2. data/HISTORY.md +139 -18
  3. data/README.rdoc +17 -25
  4. data/Rakefile +6 -14
  5. data/SPEC +8 -9
  6. data/contrib/rack_logo.svg +164 -111
  7. data/lib/rack.rb +70 -21
  8. data/lib/rack/auth/digest/request.rb +1 -1
  9. data/lib/rack/body_proxy.rb +14 -9
  10. data/lib/rack/builder.rb +3 -3
  11. data/lib/rack/chunked.rb +5 -5
  12. data/lib/rack/{commonlogger.rb → common_logger.rb} +2 -2
  13. data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
  14. data/lib/rack/content_length.rb +2 -2
  15. data/lib/rack/deflater.rb +4 -4
  16. data/lib/rack/directory.rb +49 -55
  17. data/lib/rack/etag.rb +2 -1
  18. data/lib/rack/events.rb +154 -0
  19. data/lib/rack/file.rb +55 -40
  20. data/lib/rack/handler.rb +2 -24
  21. data/lib/rack/handler/cgi.rb +15 -16
  22. data/lib/rack/handler/fastcgi.rb +13 -14
  23. data/lib/rack/handler/lsws.rb +11 -11
  24. data/lib/rack/handler/scgi.rb +15 -15
  25. data/lib/rack/handler/thin.rb +3 -0
  26. data/lib/rack/handler/webrick.rb +22 -24
  27. data/lib/rack/head.rb +15 -17
  28. data/lib/rack/lint.rb +38 -38
  29. data/lib/rack/lobster.rb +1 -1
  30. data/lib/rack/lock.rb +6 -10
  31. data/lib/rack/logger.rb +2 -2
  32. data/lib/rack/media_type.rb +38 -0
  33. data/lib/rack/{methodoverride.rb → method_override.rb} +4 -11
  34. data/lib/rack/mime.rb +18 -5
  35. data/lib/rack/mock.rb +35 -52
  36. data/lib/rack/multipart.rb +35 -6
  37. data/lib/rack/multipart/generator.rb +4 -4
  38. data/lib/rack/multipart/parser.rb +273 -158
  39. data/lib/rack/multipart/uploaded_file.rb +1 -2
  40. data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
  41. data/lib/rack/query_parser.rb +174 -0
  42. data/lib/rack/recursive.rb +8 -8
  43. data/lib/rack/reloader.rb +1 -2
  44. data/lib/rack/request.rb +370 -304
  45. data/lib/rack/response.rb +129 -56
  46. data/lib/rack/rewindable_input.rb +1 -12
  47. data/lib/rack/runtime.rb +10 -18
  48. data/lib/rack/sendfile.rb +5 -7
  49. data/lib/rack/server.rb +31 -25
  50. data/lib/rack/session/abstract/id.rb +93 -135
  51. data/lib/rack/session/cookie.rb +26 -28
  52. data/lib/rack/session/memcache.rb +8 -14
  53. data/lib/rack/session/pool.rb +14 -21
  54. data/lib/rack/show_exceptions.rb +386 -0
  55. data/lib/rack/{showstatus.rb → show_status.rb} +3 -3
  56. data/lib/rack/static.rb +30 -5
  57. data/lib/rack/tempfile_reaper.rb +2 -2
  58. data/lib/rack/urlmap.rb +13 -14
  59. data/lib/rack/utils.rb +128 -221
  60. data/rack.gemspec +9 -5
  61. data/test/builder/an_underscore_app.rb +5 -0
  62. data/test/builder/options.ru +1 -1
  63. data/test/cgi/test.fcgi +1 -0
  64. data/test/cgi/test.gz +0 -0
  65. data/test/helper.rb +31 -0
  66. data/test/multipart/filename_with_encoded_words +7 -0
  67. data/test/multipart/{filename_with_null_byte → filename_with_single_quote} +1 -1
  68. data/test/multipart/quoted +15 -0
  69. data/test/multipart/rack-logo.png +0 -0
  70. data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
  71. data/test/spec_auth_basic.rb +20 -19
  72. data/test/spec_auth_digest.rb +47 -46
  73. data/test/spec_body_proxy.rb +27 -27
  74. data/test/spec_builder.rb +51 -41
  75. data/test/spec_cascade.rb +24 -22
  76. data/test/spec_cgi.rb +49 -67
  77. data/test/spec_chunked.rb +36 -34
  78. data/test/{spec_commonlogger.rb → spec_common_logger.rb} +23 -21
  79. data/test/{spec_conditionalget.rb → spec_conditional_get.rb} +29 -28
  80. data/test/spec_config.rb +3 -2
  81. data/test/spec_content_length.rb +18 -17
  82. data/test/spec_content_type.rb +13 -12
  83. data/test/spec_deflater.rb +66 -40
  84. data/test/spec_directory.rb +72 -27
  85. data/test/spec_etag.rb +32 -31
  86. data/test/spec_events.rb +133 -0
  87. data/test/spec_fastcgi.rb +50 -72
  88. data/test/spec_file.rb +96 -77
  89. data/test/spec_handler.rb +19 -34
  90. data/test/spec_head.rb +15 -14
  91. data/test/spec_lint.rb +162 -197
  92. data/test/spec_lobster.rb +24 -23
  93. data/test/spec_lock.rb +69 -39
  94. data/test/spec_logger.rb +4 -3
  95. data/test/spec_media_type.rb +42 -0
  96. data/test/spec_method_override.rb +83 -0
  97. data/test/spec_mime.rb +19 -19
  98. data/test/spec_mock.rb +196 -151
  99. data/test/spec_multipart.rb +310 -202
  100. data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
  101. data/test/spec_recursive.rb +17 -14
  102. data/test/spec_request.rb +763 -607
  103. data/test/spec_response.rb +209 -156
  104. data/test/spec_rewindable_input.rb +50 -40
  105. data/test/spec_runtime.rb +11 -10
  106. data/test/spec_sendfile.rb +30 -35
  107. data/test/spec_server.rb +78 -52
  108. data/test/spec_session_abstract_id.rb +11 -33
  109. data/test/spec_session_cookie.rb +97 -65
  110. data/test/spec_session_memcache.rb +63 -101
  111. data/test/spec_session_pool.rb +48 -84
  112. data/test/spec_show_exceptions.rb +80 -0
  113. data/test/{spec_showstatus.rb → spec_show_status.rb} +36 -35
  114. data/test/spec_static.rb +71 -32
  115. data/test/spec_tempfile_reaper.rb +11 -10
  116. data/test/spec_thin.rb +55 -50
  117. data/test/spec_urlmap.rb +79 -78
  118. data/test/spec_utils.rb +417 -345
  119. data/test/spec_version.rb +2 -8
  120. data/test/spec_webrick.rb +77 -67
  121. data/test/static/foo.html +1 -0
  122. data/test/testrequest.rb +1 -1
  123. data/test/unregistered_handler/rack/handler/unregistered.rb +1 -1
  124. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +1 -1
  125. metadata +116 -71
  126. data/KNOWN-ISSUES +0 -44
  127. data/lib/rack/backports/uri/common_18.rb +0 -56
  128. data/lib/rack/backports/uri/common_192.rb +0 -52
  129. data/lib/rack/backports/uri/common_193.rb +0 -29
  130. data/lib/rack/handler/evented_mongrel.rb +0 -8
  131. data/lib/rack/handler/mongrel.rb +0 -106
  132. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  133. data/lib/rack/showexceptions.rb +0 -387
  134. data/lib/rack/utils/okjson.rb +0 -600
  135. data/test/spec_methodoverride.rb +0 -111
  136. data/test/spec_mongrel.rb +0 -182
  137. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  138. data/test/spec_showexceptions.rb +0 -98
@@ -1,81 +1,48 @@
1
1
  # AUTHOR: blink <blinketje@gmail.com>; blink#ruby-lang@irc.freenode.net
2
2
  # bugrep: Andreas Zehnder
3
3
 
4
+ require 'rack'
4
5
  require 'time'
5
6
  require 'rack/request'
6
7
  require 'rack/response'
7
- begin
8
- require 'securerandom'
9
- rescue LoadError
10
- # We just won't get securerandom
11
- end
12
- require "digest/sha2"
8
+ require 'securerandom'
13
9
 
14
10
  module Rack
15
11
 
16
12
  module Session
17
13
 
18
- class SessionId
19
- ID_VERSION = 2
20
-
21
- attr_reader :public_id
22
-
23
- def initialize(public_id)
24
- @public_id = public_id
25
- end
26
-
27
- def private_id
28
- "#{ID_VERSION}::#{hash_sid(public_id)}"
29
- end
30
-
31
- alias :cookie_value :public_id
32
- alias :to_s :public_id
33
-
34
- def empty?; false; end
35
- def inspect; public_id.inspect; end
36
-
37
- private
38
-
39
- def hash_sid(sid)
40
- Digest::SHA256.hexdigest(sid)
41
- end
42
- end
43
-
44
14
  module Abstract
45
- ENV_SESSION_KEY = 'rack.session'.freeze
46
- ENV_SESSION_OPTIONS_KEY = 'rack.session.options'.freeze
47
-
48
15
  # SessionHash is responsible to lazily load the session from store.
49
16
 
50
17
  class SessionHash
51
18
  include Enumerable
52
19
  attr_writer :id
53
20
 
54
- def self.find(env)
55
- env[ENV_SESSION_KEY]
21
+ def self.find(req)
22
+ req.get_header RACK_SESSION
56
23
  end
57
24
 
58
- def self.set(env, session)
59
- env[ENV_SESSION_KEY] = session
25
+ def self.set(req, session)
26
+ req.set_header RACK_SESSION, session
60
27
  end
61
28
 
62
- def self.set_options(env, options)
63
- env[ENV_SESSION_OPTIONS_KEY] = options.dup
29
+ def self.set_options(req, options)
30
+ req.set_header RACK_SESSION_OPTIONS, options.dup
64
31
  end
65
32
 
66
- def initialize(store, env)
33
+ def initialize(store, req)
67
34
  @store = store
68
- @env = env
35
+ @req = req
69
36
  @loaded = false
70
37
  end
71
38
 
72
39
  def id
73
40
  return @id if @loaded or instance_variable_defined?(:@id)
74
- @id = @store.send(:extract_session_id, @env)
41
+ @id = @store.send(:extract_session_id, @req)
75
42
  end
76
43
 
77
44
  def options
78
- @env[ENV_SESSION_OPTIONS_KEY]
45
+ @req.session_options
79
46
  end
80
47
 
81
48
  def each(&block)
@@ -109,7 +76,7 @@ module Rack
109
76
 
110
77
  def destroy
111
78
  clear
112
- @id = @store.send(:destroy_session, @env, id, options)
79
+ @id = @store.send(:delete_session, @req, id, options)
113
80
  end
114
81
 
115
82
  def to_hash
@@ -144,7 +111,7 @@ module Rack
144
111
  def exists?
145
112
  return @exists if instance_variable_defined?(:@exists)
146
113
  @data = {}
147
- @exists = @store.send(:session_exists?, @env)
114
+ @exists = @store.send(:session_exists?, @req)
148
115
  end
149
116
 
150
117
  def loaded?
@@ -175,7 +142,7 @@ module Rack
175
142
  end
176
143
 
177
144
  def load!
178
- @id, session = @store.send(:load_session, @env)
145
+ @id, session = @store.send(:load_session, @req)
179
146
  @data = stringify_keys(session)
180
147
  @loaded = true
181
148
  end
@@ -191,7 +158,7 @@ module Rack
191
158
 
192
159
  # ID sets up a basic framework for implementing an id based sessioning
193
160
  # service. Cookies sent to the client for maintaining sessions will only
194
- # contain an id reference. Only #get_session and #set_session are
161
+ # contain an id reference. Only #find_session and #write_session are
195
162
  # required to be overwritten.
196
163
  #
197
164
  # All parameters are optional.
@@ -209,9 +176,9 @@ module Rack
209
176
  # id will be.
210
177
  #
211
178
  # These options can be set on a per request basis, at the location of
212
- # env['rack.session.options']. Additionally the id of the session can be
213
- # found within the options hash at the key :id. It is highly not
214
- # recommended to change its value.
179
+ # <tt>env['rack.session.options']</tt>. Additionally the id of the
180
+ # session can be found within the options hash at the key :id. It is
181
+ # highly not recommended to change its value.
215
182
  #
216
183
  # Is Rack::Utils::Context compatible.
217
184
  #
@@ -220,7 +187,7 @@ module Rack
220
187
 
221
188
  class Persisted
222
189
  DEFAULT_OPTIONS = {
223
- :key => 'rack.session',
190
+ :key => RACK_SESSION,
224
191
  :path => '/',
225
192
  :domain => nil,
226
193
  :expire_after => nil,
@@ -230,10 +197,10 @@ module Rack
230
197
  :renew => false,
231
198
  :sidbits => 128,
232
199
  :cookie_only => true,
233
- :secure_random => (::SecureRandom rescue false)
200
+ :secure_random => ::SecureRandom
234
201
  }
235
202
 
236
- attr_reader :key, :default_options
203
+ attr_reader :key, :default_options, :sid_secure
237
204
 
238
205
  def initialize(app, options={})
239
206
  @app = app
@@ -248,13 +215,20 @@ module Rack
248
215
  end
249
216
 
250
217
  def context(env, app=@app)
251
- prepare_session(env)
252
- status, headers, body = app.call(env)
253
- commit_session(env, status, headers, body)
218
+ req = make_request env
219
+ prepare_session(req)
220
+ status, headers, body = app.call(req.env)
221
+ res = Rack::Response::Raw.new status, headers
222
+ commit_session(req, res)
223
+ [status, headers, body]
254
224
  end
255
225
 
256
226
  private
257
227
 
228
+ def make_request(env)
229
+ Rack::Request.new env
230
+ end
231
+
258
232
  def initialize_sid
259
233
  @sidbits = @default_options[:sidbits]
260
234
  @sid_secure = @default_options[:secure_random]
@@ -278,26 +252,26 @@ module Rack
278
252
  # Sets the lazy session at 'rack.session' and places options and session
279
253
  # metadata into 'rack.session.options'.
280
254
 
281
- def prepare_session(env)
282
- session_was = env[ENV_SESSION_KEY]
283
- env[ENV_SESSION_KEY] = session_class.new(self, env)
284
- env[ENV_SESSION_OPTIONS_KEY] = @default_options.dup
285
- env[ENV_SESSION_KEY].merge! session_was if session_was
255
+ def prepare_session(req)
256
+ session_was = req.get_header RACK_SESSION
257
+ session = session_class.new(self, req)
258
+ req.set_header RACK_SESSION, session
259
+ req.set_header RACK_SESSION_OPTIONS, @default_options.dup
260
+ session.merge! session_was if session_was
286
261
  end
287
262
 
288
263
  # Extracts the session id from provided cookies and passes it and the
289
- # environment to #get_session.
264
+ # environment to #find_session.
290
265
 
291
- def load_session(env)
292
- sid = current_session_id(env)
293
- sid, session = get_session(env, sid)
266
+ def load_session(req)
267
+ sid = current_session_id(req)
268
+ sid, session = find_session(req, sid)
294
269
  [sid, session || {}]
295
270
  end
296
271
 
297
272
  # Extract session id from request object.
298
273
 
299
- def extract_session_id(env)
300
- request = Rack::Request.new(env)
274
+ def extract_session_id(request)
301
275
  sid = request.cookies[@key]
302
276
  sid ||= request.params[@key] unless @cookie_only
303
277
  sid
@@ -305,26 +279,26 @@ module Rack
305
279
 
306
280
  # Returns the current session id from the SessionHash.
307
281
 
308
- def current_session_id(env)
309
- env[ENV_SESSION_KEY].id
282
+ def current_session_id(req)
283
+ req.get_header(RACK_SESSION).id
310
284
  end
311
285
 
312
286
  # Check if the session exists or not.
313
287
 
314
- def session_exists?(env)
315
- value = current_session_id(env)
288
+ def session_exists?(req)
289
+ value = current_session_id(req)
316
290
  value && !value.empty?
317
291
  end
318
292
 
319
293
  # Session should be committed if it was loaded, any of specific options like :renew, :drop
320
294
  # or :expire_after was given and the security permissions match. Skips if skip is given.
321
295
 
322
- def commit_session?(env, session, options)
296
+ def commit_session?(req, session, options)
323
297
  if options[:skip]
324
298
  false
325
299
  else
326
300
  has_session = loaded_session?(session) || forced_session_update?(session, options)
327
- has_session && security_matches?(env, options)
301
+ has_session && security_matches?(req, options)
328
302
  end
329
303
  end
330
304
 
@@ -340,58 +314,52 @@ module Rack
340
314
  options.values_at(:max_age, :renew, :drop, :defer, :expire_after).any?
341
315
  end
342
316
 
343
- def security_matches?(env, options)
317
+ def security_matches?(request, options)
344
318
  return true unless options[:secure]
345
- request = Rack::Request.new(env)
346
319
  request.ssl?
347
320
  end
348
321
 
349
322
  # Acquires the session from the environment and the session id from
350
- # the session options and passes them to #set_session. If successful
323
+ # the session options and passes them to #write_session. If successful
351
324
  # and the :defer option is not true, a cookie will be added to the
352
325
  # response with the session's id.
353
326
 
354
- def commit_session(env, status, headers, body)
355
- session = env[ENV_SESSION_KEY]
327
+ def commit_session(req, res)
328
+ session = req.get_header RACK_SESSION
356
329
  options = session.options
357
330
 
358
331
  if options[:drop] || options[:renew]
359
- session_id = destroy_session(env, session.id || generate_sid, options)
360
- return [status, headers, body] unless session_id
332
+ session_id = delete_session(req, session.id || generate_sid, options)
333
+ return unless session_id
361
334
  end
362
335
 
363
- return [status, headers, body] unless commit_session?(env, session, options)
336
+ return unless commit_session?(req, session, options)
364
337
 
365
338
  session.send(:load!) unless loaded_session?(session)
366
339
  session_id ||= session.id
367
340
  session_data = session.to_hash.delete_if { |k,v| v.nil? }
368
341
 
369
- if not data = set_session(env, session_id, session_data, options)
370
- env["rack.errors"].puts("Warning! #{self.class.name} failed to save session. Content dropped.")
342
+ if not data = write_session(req, session_id, session_data, options)
343
+ req.get_header(RACK_ERRORS).puts("Warning! #{self.class.name} failed to save session. Content dropped.")
371
344
  elsif options[:defer] and not options[:renew]
372
- env["rack.errors"].puts("Deferring cookie for #{session_id.public_id}") if $VERBOSE
345
+ req.get_header(RACK_ERRORS).puts("Deferring cookie for #{session_id}") if $VERBOSE
373
346
  else
374
347
  cookie = Hash.new
375
- cookie[:value] = cookie_value(data)
348
+ cookie[:value] = data
376
349
  cookie[:expires] = Time.now + options[:expire_after] if options[:expire_after]
377
350
  cookie[:expires] = Time.now + options[:max_age] if options[:max_age]
378
- set_cookie(env, headers, cookie.merge!(options))
351
+ set_cookie(req, res, cookie.merge!(options))
379
352
  end
380
-
381
- [status, headers, body]
382
- end
383
-
384
- def cookie_value(data)
385
- data
386
353
  end
354
+ public :commit_session
387
355
 
388
356
  # Sets the cookie back to the client with session id. We skip the cookie
389
357
  # setting if the value didn't change (sid is the same) or expires was given.
390
358
 
391
- def set_cookie(env, headers, cookie)
392
- request = Rack::Request.new(env)
359
+ def set_cookie(request, res, cookie)
393
360
  if request.cookies[@key] != cookie[:value] || cookie[:expires]
394
- Utils.set_cookie_header!(headers, @key, cookie)
361
+ res.set_cookie_header =
362
+ Utils.add_cookie_to_header(res.set_cookie_header, @key, cookie)
395
363
  end
396
364
  end
397
365
 
@@ -406,68 +374,58 @@ module Rack
406
374
  # If nil is provided as the session id, generation of a new valid id
407
375
  # should occur within.
408
376
 
409
- def get_session(env, sid)
410
- raise '#get_session not implemented.'
377
+ def find_session(env, sid)
378
+ raise '#find_session not implemented.'
411
379
  end
412
380
 
413
381
  # All thread safety and session storage procedures should occur here.
414
382
  # Must return the session id if the session was saved successfully, or
415
383
  # false if the session could not be saved.
416
384
 
417
- def set_session(env, sid, session, options)
418
- raise '#set_session not implemented.'
385
+ def write_session(req, sid, session, options)
386
+ raise '#write_session not implemented.'
419
387
  end
420
388
 
421
389
  # All thread safety and session destroy procedures should occur here.
422
390
  # Should return a new session id or nil if options[:drop]
423
391
 
424
- def destroy_session(env, sid, options)
425
- raise '#destroy_session not implemented'
392
+ def delete_session(req, sid, options)
393
+ raise '#delete_session not implemented'
426
394
  end
427
395
  end
428
396
 
429
- class PersistedSecure < Persisted
430
- class SecureSessionHash < SessionHash
431
- def [](key)
432
- if key == "session_id"
433
- load_for_read!
434
- id.public_id if id
435
- else
436
- super
437
- end
397
+ class ID < Persisted
398
+ def self.inherited(klass)
399
+ k = klass.ancestors.find { |kl| kl.superclass == ID }
400
+ unless k.instance_variable_defined?(:"@_rack_warned")
401
+ warn "#{klass} is inheriting from #{ID}. Inheriting from #{ID} is deprecated, please inherit from #{Persisted} instead" if $VERBOSE
402
+ k.instance_variable_set(:"@_rack_warned", true)
438
403
  end
404
+ super
439
405
  end
440
406
 
441
- def generate_sid(*)
442
- public_id = super
443
-
444
- SessionId.new(public_id)
445
- end
407
+ # All thread safety and session retrieval procedures should occur here.
408
+ # Should return [session_id, session].
409
+ # If nil is provided as the session id, generation of a new valid id
410
+ # should occur within.
446
411
 
447
- def extract_session_id(*)
448
- public_id = super
449
- public_id && SessionId.new(public_id)
412
+ def find_session(req, sid)
413
+ get_session req.env, sid
450
414
  end
451
415
 
452
- private
416
+ # All thread safety and session storage procedures should occur here.
417
+ # Must return the session id if the session was saved successfully, or
418
+ # false if the session could not be saved.
453
419
 
454
- def session_class
455
- SecureSessionHash
420
+ def write_session(req, sid, session, options)
421
+ set_session req.env, sid, session, options
456
422
  end
457
423
 
458
- def cookie_value(data)
459
- data.cookie_value
460
- end
461
- end
424
+ # All thread safety and session destroy procedures should occur here.
425
+ # Should return a new session id or nil if options[:drop]
462
426
 
463
- class ID < Persisted
464
- def self.inherited(klass)
465
- k = klass.ancestors.find { |kl| kl.respond_to?(:superclass) && kl.superclass == ID }
466
- unless k.instance_variable_defined?(:"@_rack_warned")
467
- warn "#{klass} is inheriting from #{ID}. Inheriting from #{ID} is deprecated, please inherit from #{Persisted} instead" if $VERBOSE
468
- k.instance_variable_set(:"@_rack_warned", true)
469
- end
470
- super
427
+ def delete_session(req, sid, options)
428
+ destroy_session req.env, sid, options
471
429
  end
472
430
  end
473
431
  end
@@ -3,6 +3,7 @@ require 'zlib'
3
3
  require 'rack/request'
4
4
  require 'rack/response'
5
5
  require 'rack/session/abstract/id'
6
+ require 'json'
6
7
 
7
8
  module Rack
8
9
 
@@ -44,7 +45,7 @@ module Rack
44
45
  # })
45
46
  #
46
47
 
47
- class Cookie < Abstract::PersistedSecure
48
+ class Cookie < Abstract::Persisted
48
49
  # Encode session cookies as Base64
49
50
  class Base64
50
51
  def encode(str)
@@ -71,23 +72,23 @@ module Rack
71
72
  # valid JSON composite type, either a Hash or an Array.
72
73
  class JSON < Base64
73
74
  def encode(obj)
74
- super(::Rack::Utils::OkJson.encode(obj))
75
+ super(::JSON.dump(obj))
75
76
  end
76
77
 
77
78
  def decode(str)
78
79
  return unless str
79
- ::Rack::Utils::OkJson.decode(super(str)) rescue nil
80
+ ::JSON.parse(super(str)) rescue nil
80
81
  end
81
82
  end
82
83
 
83
84
  class ZipJSON < Base64
84
85
  def encode(obj)
85
- super(Zlib::Deflate.deflate(::Rack::Utils::OkJson.encode(obj)))
86
+ super(Zlib::Deflate.deflate(::JSON.dump(obj)))
86
87
  end
87
88
 
88
89
  def decode(str)
89
90
  return unless str
90
- ::Rack::Utils::OkJson.decode(Zlib::Inflate.inflate(super(str)))
91
+ ::JSON.parse(Zlib::Inflate.inflate(super(str)))
91
92
  rescue
92
93
  nil
93
94
  end
@@ -104,7 +105,9 @@ module Rack
104
105
 
105
106
  def initialize(app, options={})
106
107
  @secrets = options.values_at(:secret, :old_secret).compact
107
- warn <<-MSG unless @secrets.size >= 1
108
+ @hmac = options.fetch(:hmac, OpenSSL::Digest::SHA1)
109
+
110
+ warn <<-MSG unless secure?(options)
108
111
  SECURITY WARNING: No secret option provided to Rack::Session::Cookie.
109
112
  This poses a security threat. It is strongly recommended that you
110
113
  provide a secret to prevent exploits that may be possible from crafted
@@ -119,19 +122,18 @@ module Rack
119
122
 
120
123
  private
121
124
 
122
- def get_session(env, sid)
123
- data = unpacked_cookie_data(env)
125
+ def find_session(req, sid)
126
+ data = unpacked_cookie_data(req)
124
127
  data = persistent_session_id!(data)
125
128
  [data["session_id"], data]
126
129
  end
127
130
 
128
- def extract_session_id(env)
129
- unpacked_cookie_data(env)["session_id"]
131
+ def extract_session_id(request)
132
+ unpacked_cookie_data(request)["session_id"]
130
133
  end
131
134
 
132
- def unpacked_cookie_data(env)
133
- env["rack.session.unpacked_cookie_data"] ||= begin
134
- request = Rack::Request.new(env)
135
+ def unpacked_cookie_data(request)
136
+ request.fetch_header(RACK_SESSION_UNPACKED_COOKIE_DATA) do |k|
135
137
  session_data = request.cookies[@key]
136
138
 
137
139
  if @secrets.size > 0 && session_data
@@ -141,7 +143,7 @@ module Rack
141
143
  session_data = nil unless digest_match?(session_data, digest)
142
144
  end
143
145
 
144
- coder.decode(session_data) || {}
146
+ request.set_header(k, coder.decode(session_data) || {})
145
147
  end
146
148
  end
147
149
 
@@ -151,16 +153,7 @@ module Rack
151
153
  data
152
154
  end
153
155
 
154
- class SessionId < DelegateClass(Session::SessionId)
155
- attr_reader :cookie_value
156
-
157
- def initialize(session_id, cookie_value)
158
- super(session_id)
159
- @cookie_value = cookie_value
160
- end
161
- end
162
-
163
- def set_session(env, session_id, session, options)
156
+ def write_session(req, session_id, session, options)
164
157
  session = session.merge("session_id" => session_id)
165
158
  session_data = coder.encode(session)
166
159
 
@@ -169,14 +162,14 @@ module Rack
169
162
  end
170
163
 
171
164
  if session_data.size > (4096 - @key.size)
172
- env["rack.errors"].puts("Warning! Rack::Session::Cookie data size exceeds 4K.")
165
+ req.get_header(RACK_ERRORS).puts("Warning! Rack::Session::Cookie data size exceeds 4K.")
173
166
  nil
174
167
  else
175
- SessionId.new(session_id, session_data)
168
+ session_data
176
169
  end
177
170
  end
178
171
 
179
- def destroy_session(env, session_id, options)
172
+ def delete_session(req, session_id, options)
180
173
  # Nothing to do here, data is in the client
181
174
  generate_sid unless options[:drop]
182
175
  end
@@ -189,7 +182,12 @@ module Rack
189
182
  end
190
183
 
191
184
  def generate_hmac(data, secret)
192
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, secret, data)
185
+ OpenSSL::HMAC.hexdigest(@hmac.new, secret, data)
186
+ end
187
+
188
+ def secure?(options)
189
+ @secrets.size >= 1 ||
190
+ (options[:coder] && options[:let_coder_handle_secure_encoding])
193
191
  end
194
192
 
195
193
  end