rack 1.6.13 → 2.0.9.3

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 (142) hide show
  1. checksums.yaml +4 -4
  2. data/COPYING +1 -1
  3. data/HISTORY.md +153 -8
  4. data/README.rdoc +35 -31
  5. data/Rakefile +6 -14
  6. data/SPEC +10 -11
  7. data/contrib/rack_logo.svg +164 -111
  8. data/example/protectedlobster.rb +1 -1
  9. data/example/protectedlobster.ru +1 -1
  10. data/lib/rack/auth/abstract/request.rb +5 -1
  11. data/lib/rack/auth/digest/params.rb +2 -3
  12. data/lib/rack/auth/digest/request.rb +1 -1
  13. data/lib/rack/body_proxy.rb +14 -9
  14. data/lib/rack/builder.rb +3 -3
  15. data/lib/rack/chunked.rb +5 -5
  16. data/lib/rack/{commonlogger.rb → common_logger.rb} +6 -3
  17. data/lib/rack/content_length.rb +2 -2
  18. data/lib/rack/deflater.rb +4 -39
  19. data/lib/rack/directory.rb +66 -54
  20. data/lib/rack/etag.rb +5 -4
  21. data/lib/rack/events.rb +154 -0
  22. data/lib/rack/file.rb +64 -40
  23. data/lib/rack/handler/cgi.rb +15 -16
  24. data/lib/rack/handler/fastcgi.rb +13 -14
  25. data/lib/rack/handler/lsws.rb +11 -11
  26. data/lib/rack/handler/scgi.rb +15 -15
  27. data/lib/rack/handler/thin.rb +3 -0
  28. data/lib/rack/handler/webrick.rb +24 -26
  29. data/lib/rack/handler.rb +3 -25
  30. data/lib/rack/head.rb +15 -17
  31. data/lib/rack/lint.rb +41 -41
  32. data/lib/rack/lobster.rb +1 -1
  33. data/lib/rack/lock.rb +15 -10
  34. data/lib/rack/logger.rb +2 -2
  35. data/lib/rack/media_type.rb +38 -0
  36. data/lib/rack/{methodoverride.rb → method_override.rb} +6 -6
  37. data/lib/rack/mime.rb +18 -5
  38. data/lib/rack/mock.rb +36 -54
  39. data/lib/rack/multipart/generator.rb +5 -5
  40. data/lib/rack/multipart/parser.rb +283 -157
  41. data/lib/rack/multipart/uploaded_file.rb +1 -2
  42. data/lib/rack/multipart.rb +36 -8
  43. data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
  44. data/lib/rack/query_parser.rb +192 -0
  45. data/lib/rack/recursive.rb +8 -8
  46. data/lib/rack/request.rb +394 -305
  47. data/lib/rack/response.rb +130 -57
  48. data/lib/rack/rewindable_input.rb +1 -12
  49. data/lib/rack/runtime.rb +10 -18
  50. data/lib/rack/sendfile.rb +5 -7
  51. data/lib/rack/server.rb +30 -23
  52. data/lib/rack/session/abstract/id.rb +110 -75
  53. data/lib/rack/session/cookie.rb +24 -17
  54. data/lib/rack/session/memcache.rb +9 -9
  55. data/lib/rack/session/pool.rb +8 -8
  56. data/lib/rack/show_exceptions.rb +386 -0
  57. data/lib/rack/{showstatus.rb → show_status.rb} +3 -3
  58. data/lib/rack/static.rb +30 -5
  59. data/lib/rack/tempfile_reaper.rb +2 -2
  60. data/lib/rack/urlmap.rb +15 -14
  61. data/lib/rack/utils.rb +156 -217
  62. data/lib/rack.rb +70 -21
  63. data/rack.gemspec +10 -9
  64. data/test/builder/an_underscore_app.rb +5 -0
  65. data/test/builder/options.ru +1 -1
  66. data/test/cgi/test.fcgi +1 -0
  67. data/test/cgi/test.gz +0 -0
  68. data/test/helper.rb +34 -0
  69. data/test/multipart/filename_with_encoded_words +7 -0
  70. data/test/multipart/filename_with_escaped_quotes_and_modification_param +1 -1
  71. data/test/multipart/filename_with_single_quote +7 -0
  72. data/test/multipart/quoted +15 -0
  73. data/test/multipart/rack-logo.png +0 -0
  74. data/test/multipart/unity3d_wwwform +11 -0
  75. data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
  76. data/test/spec_auth_basic.rb +27 -19
  77. data/test/spec_auth_digest.rb +47 -46
  78. data/test/spec_body_proxy.rb +27 -27
  79. data/test/spec_builder.rb +51 -41
  80. data/test/spec_cascade.rb +24 -22
  81. data/test/spec_cgi.rb +49 -67
  82. data/test/spec_chunked.rb +37 -35
  83. data/test/{spec_commonlogger.rb → spec_common_logger.rb} +35 -21
  84. data/test/{spec_conditionalget.rb → spec_conditional_get.rb} +29 -28
  85. data/test/spec_config.rb +3 -2
  86. data/test/spec_content_length.rb +18 -17
  87. data/test/spec_content_type.rb +13 -12
  88. data/test/spec_deflater.rb +85 -49
  89. data/test/spec_directory.rb +87 -27
  90. data/test/spec_etag.rb +32 -31
  91. data/test/spec_events.rb +133 -0
  92. data/test/spec_fastcgi.rb +50 -72
  93. data/test/spec_file.rb +120 -77
  94. data/test/spec_handler.rb +19 -34
  95. data/test/spec_head.rb +15 -14
  96. data/test/spec_lint.rb +169 -199
  97. data/test/spec_lobster.rb +24 -23
  98. data/test/spec_lock.rb +79 -39
  99. data/test/spec_logger.rb +4 -3
  100. data/test/spec_media_type.rb +42 -0
  101. data/test/{spec_methodoverride.rb → spec_method_override.rb} +34 -35
  102. data/test/spec_mime.rb +19 -19
  103. data/test/spec_mock.rb +206 -144
  104. data/test/spec_multipart.rb +329 -208
  105. data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
  106. data/test/spec_recursive.rb +17 -14
  107. data/test/spec_request.rb +796 -605
  108. data/test/spec_response.rb +233 -112
  109. data/test/spec_rewindable_input.rb +50 -40
  110. data/test/spec_runtime.rb +11 -10
  111. data/test/spec_sendfile.rb +30 -35
  112. data/test/spec_server.rb +78 -52
  113. data/test/spec_session_abstract_id.rb +11 -33
  114. data/test/spec_session_abstract_session_hash.rb +45 -0
  115. data/test/spec_session_cookie.rb +99 -67
  116. data/test/spec_session_memcache.rb +67 -68
  117. data/test/spec_session_pool.rb +52 -51
  118. data/test/{spec_showexceptions.rb → spec_show_exceptions.rb} +23 -28
  119. data/test/{spec_showstatus.rb → spec_show_status.rb} +36 -35
  120. data/test/spec_static.rb +71 -32
  121. data/test/spec_tempfile_reaper.rb +11 -10
  122. data/test/spec_thin.rb +55 -50
  123. data/test/spec_urlmap.rb +79 -78
  124. data/test/spec_utils.rb +441 -346
  125. data/test/spec_version.rb +2 -8
  126. data/test/spec_webrick.rb +93 -71
  127. data/test/static/foo.html +1 -0
  128. data/test/testrequest.rb +1 -1
  129. data/test/unregistered_handler/rack/handler/unregistered.rb +1 -1
  130. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +1 -1
  131. metadata +95 -74
  132. data/KNOWN-ISSUES +0 -44
  133. data/lib/rack/backports/uri/common_18.rb +0 -56
  134. data/lib/rack/backports/uri/common_192.rb +0 -52
  135. data/lib/rack/backports/uri/common_193.rb +0 -29
  136. data/lib/rack/handler/evented_mongrel.rb +0 -8
  137. data/lib/rack/handler/mongrel.rb +0 -106
  138. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  139. data/lib/rack/showexceptions.rb +0 -387
  140. data/lib/rack/utils/okjson.rb +0 -600
  141. data/test/spec_mongrel.rb +0 -182
  142. /data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
@@ -1,15 +1,12 @@
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'
9
+ require 'digest/sha2'
13
10
 
14
11
  module Rack
15
12
 
@@ -42,40 +39,39 @@ module Rack
42
39
  end
43
40
 
44
41
  module Abstract
45
- ENV_SESSION_KEY = 'rack.session'.freeze
46
- ENV_SESSION_OPTIONS_KEY = 'rack.session.options'.freeze
47
-
48
42
  # SessionHash is responsible to lazily load the session from store.
49
43
 
50
44
  class SessionHash
51
45
  include Enumerable
52
46
  attr_writer :id
53
47
 
54
- def self.find(env)
55
- env[ENV_SESSION_KEY]
48
+ Unspecified = Object.new
49
+
50
+ def self.find(req)
51
+ req.get_header RACK_SESSION
56
52
  end
57
53
 
58
- def self.set(env, session)
59
- env[ENV_SESSION_KEY] = session
54
+ def self.set(req, session)
55
+ req.set_header RACK_SESSION, session
60
56
  end
61
57
 
62
- def self.set_options(env, options)
63
- env[ENV_SESSION_OPTIONS_KEY] = options.dup
58
+ def self.set_options(req, options)
59
+ req.set_header RACK_SESSION_OPTIONS, options.dup
64
60
  end
65
61
 
66
- def initialize(store, env)
62
+ def initialize(store, req)
67
63
  @store = store
68
- @env = env
64
+ @req = req
69
65
  @loaded = false
70
66
  end
71
67
 
72
68
  def id
73
69
  return @id if @loaded or instance_variable_defined?(:@id)
74
- @id = @store.send(:extract_session_id, @env)
70
+ @id = @store.send(:extract_session_id, @req)
75
71
  end
76
72
 
77
73
  def options
78
- @env[ENV_SESSION_OPTIONS_KEY]
74
+ @req.session_options
79
75
  end
80
76
 
81
77
  def each(&block)
@@ -87,7 +83,15 @@ module Rack
87
83
  load_for_read!
88
84
  @data[key.to_s]
89
85
  end
90
- alias :fetch :[]
86
+
87
+ def fetch(key, default=Unspecified, &block)
88
+ load_for_read!
89
+ if default == Unspecified
90
+ @data.fetch(key.to_s, &block)
91
+ else
92
+ @data.fetch(key.to_s, default, &block)
93
+ end
94
+ end
91
95
 
92
96
  def has_key?(key)
93
97
  load_for_read!
@@ -109,7 +113,7 @@ module Rack
109
113
 
110
114
  def destroy
111
115
  clear
112
- @id = @store.send(:destroy_session, @env, id, options)
116
+ @id = @store.send(:delete_session, @req, id, options)
113
117
  end
114
118
 
115
119
  def to_hash
@@ -144,7 +148,7 @@ module Rack
144
148
  def exists?
145
149
  return @exists if instance_variable_defined?(:@exists)
146
150
  @data = {}
147
- @exists = @store.send(:session_exists?, @env)
151
+ @exists = @store.send(:session_exists?, @req)
148
152
  end
149
153
 
150
154
  def loaded?
@@ -157,10 +161,12 @@ module Rack
157
161
  end
158
162
 
159
163
  def keys
164
+ load_for_read!
160
165
  @data.keys
161
166
  end
162
167
 
163
168
  def values
169
+ load_for_read!
164
170
  @data.values
165
171
  end
166
172
 
@@ -175,7 +181,7 @@ module Rack
175
181
  end
176
182
 
177
183
  def load!
178
- @id, session = @store.send(:load_session, @env)
184
+ @id, session = @store.send(:load_session, @req)
179
185
  @data = stringify_keys(session)
180
186
  @loaded = true
181
187
  end
@@ -191,14 +197,14 @@ module Rack
191
197
 
192
198
  # ID sets up a basic framework for implementing an id based sessioning
193
199
  # service. Cookies sent to the client for maintaining sessions will only
194
- # contain an id reference. Only #get_session and #set_session are
200
+ # contain an id reference. Only #find_session and #write_session are
195
201
  # required to be overwritten.
196
202
  #
197
203
  # All parameters are optional.
198
204
  # * :key determines the name of the cookie, by default it is
199
205
  # 'rack.session'
200
206
  # * :path, :domain, :expire_after, :secure, and :httponly set the related
201
- # cookie options as by Rack::Response#add_cookie
207
+ # cookie options as by Rack::Response#set_cookie
202
208
  # * :skip will not a set a cookie in the response nor update the session state
203
209
  # * :defer will not set a cookie in the response but still update the session
204
210
  # state if it is used with a backend
@@ -209,9 +215,9 @@ module Rack
209
215
  # id will be.
210
216
  #
211
217
  # 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.
218
+ # <tt>env['rack.session.options']</tt>. Additionally the id of the
219
+ # session can be found within the options hash at the key :id. It is
220
+ # highly not recommended to change its value.
215
221
  #
216
222
  # Is Rack::Utils::Context compatible.
217
223
  #
@@ -220,7 +226,7 @@ module Rack
220
226
 
221
227
  class Persisted
222
228
  DEFAULT_OPTIONS = {
223
- :key => 'rack.session',
229
+ :key => RACK_SESSION,
224
230
  :path => '/',
225
231
  :domain => nil,
226
232
  :expire_after => nil,
@@ -230,10 +236,10 @@ module Rack
230
236
  :renew => false,
231
237
  :sidbits => 128,
232
238
  :cookie_only => true,
233
- :secure_random => (::SecureRandom rescue false)
234
- }
239
+ :secure_random => ::SecureRandom
240
+ }.freeze
235
241
 
236
- attr_reader :key, :default_options
242
+ attr_reader :key, :default_options, :sid_secure
237
243
 
238
244
  def initialize(app, options={})
239
245
  @app = app
@@ -248,13 +254,20 @@ module Rack
248
254
  end
249
255
 
250
256
  def context(env, app=@app)
251
- prepare_session(env)
252
- status, headers, body = app.call(env)
253
- commit_session(env, status, headers, body)
257
+ req = make_request env
258
+ prepare_session(req)
259
+ status, headers, body = app.call(req.env)
260
+ res = Rack::Response::Raw.new status, headers
261
+ commit_session(req, res)
262
+ [status, headers, body]
254
263
  end
255
264
 
256
265
  private
257
266
 
267
+ def make_request(env)
268
+ Rack::Request.new env
269
+ end
270
+
258
271
  def initialize_sid
259
272
  @sidbits = @default_options[:sidbits]
260
273
  @sid_secure = @default_options[:secure_random]
@@ -278,26 +291,26 @@ module Rack
278
291
  # Sets the lazy session at 'rack.session' and places options and session
279
292
  # metadata into 'rack.session.options'.
280
293
 
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
294
+ def prepare_session(req)
295
+ session_was = req.get_header RACK_SESSION
296
+ session = session_class.new(self, req)
297
+ req.set_header RACK_SESSION, session
298
+ req.set_header RACK_SESSION_OPTIONS, @default_options.dup
299
+ session.merge! session_was if session_was
286
300
  end
287
301
 
288
302
  # Extracts the session id from provided cookies and passes it and the
289
- # environment to #get_session.
303
+ # environment to #find_session.
290
304
 
291
- def load_session(env)
292
- sid = current_session_id(env)
293
- sid, session = get_session(env, sid)
305
+ def load_session(req)
306
+ sid = current_session_id(req)
307
+ sid, session = find_session(req, sid)
294
308
  [sid, session || {}]
295
309
  end
296
310
 
297
311
  # Extract session id from request object.
298
312
 
299
- def extract_session_id(env)
300
- request = Rack::Request.new(env)
313
+ def extract_session_id(request)
301
314
  sid = request.cookies[@key]
302
315
  sid ||= request.params[@key] unless @cookie_only
303
316
  sid
@@ -305,26 +318,26 @@ module Rack
305
318
 
306
319
  # Returns the current session id from the SessionHash.
307
320
 
308
- def current_session_id(env)
309
- env[ENV_SESSION_KEY].id
321
+ def current_session_id(req)
322
+ req.get_header(RACK_SESSION).id
310
323
  end
311
324
 
312
325
  # Check if the session exists or not.
313
326
 
314
- def session_exists?(env)
315
- value = current_session_id(env)
327
+ def session_exists?(req)
328
+ value = current_session_id(req)
316
329
  value && !value.empty?
317
330
  end
318
331
 
319
332
  # Session should be committed if it was loaded, any of specific options like :renew, :drop
320
333
  # or :expire_after was given and the security permissions match. Skips if skip is given.
321
334
 
322
- def commit_session?(env, session, options)
335
+ def commit_session?(req, session, options)
323
336
  if options[:skip]
324
337
  false
325
338
  else
326
339
  has_session = loaded_session?(session) || forced_session_update?(session, options)
327
- has_session && security_matches?(env, options)
340
+ has_session && security_matches?(req, options)
328
341
  end
329
342
  end
330
343
 
@@ -340,46 +353,44 @@ module Rack
340
353
  options.values_at(:max_age, :renew, :drop, :defer, :expire_after).any?
341
354
  end
342
355
 
343
- def security_matches?(env, options)
356
+ def security_matches?(request, options)
344
357
  return true unless options[:secure]
345
- request = Rack::Request.new(env)
346
358
  request.ssl?
347
359
  end
348
360
 
349
361
  # Acquires the session from the environment and the session id from
350
- # the session options and passes them to #set_session. If successful
362
+ # the session options and passes them to #write_session. If successful
351
363
  # and the :defer option is not true, a cookie will be added to the
352
364
  # response with the session's id.
353
365
 
354
- def commit_session(env, status, headers, body)
355
- session = env[ENV_SESSION_KEY]
366
+ def commit_session(req, res)
367
+ session = req.get_header RACK_SESSION
356
368
  options = session.options
357
369
 
358
370
  if options[:drop] || options[:renew]
359
- session_id = destroy_session(env, session.id || generate_sid, options)
360
- return [status, headers, body] unless session_id
371
+ session_id = delete_session(req, session.id || generate_sid, options)
372
+ return unless session_id
361
373
  end
362
374
 
363
- return [status, headers, body] unless commit_session?(env, session, options)
375
+ return unless commit_session?(req, session, options)
364
376
 
365
377
  session.send(:load!) unless loaded_session?(session)
366
378
  session_id ||= session.id
367
379
  session_data = session.to_hash.delete_if { |k,v| v.nil? }
368
380
 
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.")
381
+ if not data = write_session(req, session_id, session_data, options)
382
+ req.get_header(RACK_ERRORS).puts("Warning! #{self.class.name} failed to save session. Content dropped.")
371
383
  elsif options[:defer] and not options[:renew]
372
- env["rack.errors"].puts("Deferring cookie for #{session_id.public_id}") if $VERBOSE
384
+ req.get_header(RACK_ERRORS).puts("Deferring cookie for #{session_id}") if $VERBOSE
373
385
  else
374
386
  cookie = Hash.new
375
387
  cookie[:value] = cookie_value(data)
376
388
  cookie[:expires] = Time.now + options[:expire_after] if options[:expire_after]
377
389
  cookie[:expires] = Time.now + options[:max_age] if options[:max_age]
378
- set_cookie(env, headers, cookie.merge!(options))
390
+ set_cookie(req, res, cookie.merge!(options))
379
391
  end
380
-
381
- [status, headers, body]
382
392
  end
393
+ public :commit_session
383
394
 
384
395
  def cookie_value(data)
385
396
  data
@@ -388,10 +399,10 @@ module Rack
388
399
  # Sets the cookie back to the client with session id. We skip the cookie
389
400
  # setting if the value didn't change (sid is the same) or expires was given.
390
401
 
391
- def set_cookie(env, headers, cookie)
392
- request = Rack::Request.new(env)
402
+ def set_cookie(request, res, cookie)
393
403
  if request.cookies[@key] != cookie[:value] || cookie[:expires]
394
- Utils.set_cookie_header!(headers, @key, cookie)
404
+ res.set_cookie_header =
405
+ Utils.add_cookie_to_header(res.set_cookie_header, @key, cookie)
395
406
  end
396
407
  end
397
408
 
@@ -406,23 +417,23 @@ module Rack
406
417
  # If nil is provided as the session id, generation of a new valid id
407
418
  # should occur within.
408
419
 
409
- def get_session(env, sid)
410
- raise '#get_session not implemented.'
420
+ def find_session(env, sid)
421
+ raise '#find_session not implemented.'
411
422
  end
412
423
 
413
424
  # All thread safety and session storage procedures should occur here.
414
425
  # Must return the session id if the session was saved successfully, or
415
426
  # false if the session could not be saved.
416
427
 
417
- def set_session(env, sid, session, options)
418
- raise '#set_session not implemented.'
428
+ def write_session(req, sid, session, options)
429
+ raise '#write_session not implemented.'
419
430
  end
420
431
 
421
432
  # All thread safety and session destroy procedures should occur here.
422
433
  # Should return a new session id or nil if options[:drop]
423
434
 
424
- def destroy_session(env, sid, options)
425
- raise '#destroy_session not implemented'
435
+ def delete_session(req, sid, options)
436
+ raise '#delete_session not implemented'
426
437
  end
427
438
  end
428
439
 
@@ -469,6 +480,30 @@ module Rack
469
480
  end
470
481
  super
471
482
  end
483
+
484
+ # All thread safety and session retrieval procedures should occur here.
485
+ # Should return [session_id, session].
486
+ # If nil is provided as the session id, generation of a new valid id
487
+ # should occur within.
488
+
489
+ def find_session(req, sid)
490
+ get_session req.env, sid
491
+ end
492
+
493
+ # All thread safety and session storage procedures should occur here.
494
+ # Must return the session id if the session was saved successfully, or
495
+ # false if the session could not be saved.
496
+
497
+ def write_session(req, sid, session, options)
498
+ set_session req.env, sid, session, options
499
+ end
500
+
501
+ # All thread safety and session destroy procedures should occur here.
502
+ # Should return a new session id or nil if options[:drop]
503
+
504
+ def delete_session(req, sid, options)
505
+ destroy_session req.env, sid, options
506
+ end
472
507
  end
473
508
  end
474
509
  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
 
@@ -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
 
@@ -160,7 +162,7 @@ module Rack
160
162
  end
161
163
  end
162
164
 
163
- def set_session(env, session_id, session, options)
165
+ def write_session(req, session_id, session, options)
164
166
  session = session.merge("session_id" => session_id)
165
167
  session_data = coder.encode(session)
166
168
 
@@ -169,14 +171,14 @@ module Rack
169
171
  end
170
172
 
171
173
  if session_data.size > (4096 - @key.size)
172
- env["rack.errors"].puts("Warning! Rack::Session::Cookie data size exceeds 4K.")
174
+ req.get_header(RACK_ERRORS).puts("Warning! Rack::Session::Cookie data size exceeds 4K.")
173
175
  nil
174
176
  else
175
177
  SessionId.new(session_id, session_data)
176
178
  end
177
179
  end
178
180
 
179
- def destroy_session(env, session_id, options)
181
+ def delete_session(req, session_id, options)
180
182
  # Nothing to do here, data is in the client
181
183
  generate_sid unless options[:drop]
182
184
  end
@@ -189,7 +191,12 @@ module Rack
189
191
  end
190
192
 
191
193
  def generate_hmac(data, secret)
192
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, secret, data)
194
+ OpenSSL::HMAC.hexdigest(@hmac.new, secret, data)
195
+ end
196
+
197
+ def secure?(options)
198
+ @secrets.size >= 1 ||
199
+ (options[:coder] && options[:let_coder_handle_secure_encoding])
193
200
  end
194
201
 
195
202
  end
@@ -34,7 +34,7 @@ module Rack
34
34
  mopts = @default_options.reject{|k,v| !MemCache::DEFAULT_OPTIONS.include? k }
35
35
 
36
36
  @pool = options[:cache] || MemCache.new(mserv, mopts)
37
- unless @pool.active? and @pool.servers.any?{|c| c.alive? }
37
+ unless @pool.active? and @pool.servers.any?(&:alive?)
38
38
  raise 'No memcache servers'
39
39
  end
40
40
  end
@@ -46,8 +46,8 @@ module Rack
46
46
  end
47
47
  end
48
48
 
49
- def get_session(env, sid)
50
- with_lock(env) do
49
+ def find_session(req, sid)
50
+ with_lock(req) do
51
51
  unless sid and session = get_session_with_fallback(sid)
52
52
  sid, session = generate_sid, {}
53
53
  unless /^STORED/ =~ @pool.add(sid.private_id, session)
@@ -58,26 +58,26 @@ module Rack
58
58
  end
59
59
  end
60
60
 
61
- def set_session(env, session_id, new_session, options)
61
+ def write_session(req, session_id, new_session, options)
62
62
  expiry = options[:expire_after]
63
63
  expiry = expiry.nil? ? 0 : expiry + 1
64
64
 
65
- with_lock(env) do
65
+ with_lock(req) do
66
66
  @pool.set session_id.private_id, new_session, expiry
67
67
  session_id
68
68
  end
69
69
  end
70
70
 
71
- def destroy_session(env, session_id, options)
72
- with_lock(env) do
71
+ def delete_session(req, session_id, options)
72
+ with_lock(req) do
73
73
  @pool.delete(session_id.public_id)
74
74
  @pool.delete(session_id.private_id)
75
75
  generate_sid unless options[:drop]
76
76
  end
77
77
  end
78
78
 
79
- def with_lock(env)
80
- @mutex.lock if env['rack.multithread']
79
+ def with_lock(req)
80
+ @mutex.lock if req.multithread?
81
81
  yield
82
82
  rescue MemCache::MemCacheError, Errno::ECONNREFUSED
83
83
  if $VERBOSE
@@ -41,8 +41,8 @@ module Rack
41
41
  end
42
42
  end
43
43
 
44
- def get_session(env, sid)
45
- with_lock(env) do
44
+ def find_session(req, sid)
45
+ with_lock(req) do
46
46
  unless sid and session = get_session_with_fallback(sid)
47
47
  sid, session = generate_sid, {}
48
48
  @pool.store sid.private_id, session
@@ -51,23 +51,23 @@ module Rack
51
51
  end
52
52
  end
53
53
 
54
- def set_session(env, session_id, new_session, options)
55
- with_lock(env) do
54
+ def write_session(req, session_id, new_session, options)
55
+ with_lock(req) do
56
56
  @pool.store session_id.private_id, new_session
57
57
  session_id
58
58
  end
59
59
  end
60
60
 
61
- def destroy_session(env, session_id, options)
62
- with_lock(env) do
61
+ def delete_session(req, session_id, options)
62
+ with_lock(req) do
63
63
  @pool.delete(session_id.public_id)
64
64
  @pool.delete(session_id.private_id)
65
65
  generate_sid unless options[:drop]
66
66
  end
67
67
  end
68
68
 
69
- def with_lock(env)
70
- @mutex.lock if env['rack.multithread']
69
+ def with_lock(req)
70
+ @mutex.lock if req.multithread?
71
71
  yield
72
72
  ensure
73
73
  @mutex.unlock if @mutex.locked?