rack 2.0.1 → 2.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +795 -0
  3. data/CONTRIBUTING.md +136 -0
  4. data/{COPYING → MIT-LICENSE} +4 -2
  5. data/README.rdoc +188 -145
  6. data/Rakefile +37 -23
  7. data/{SPEC → SPEC.rdoc} +46 -17
  8. data/bin/rackup +1 -0
  9. data/example/lobster.ru +2 -0
  10. data/example/protectedlobster.rb +3 -1
  11. data/example/protectedlobster.ru +2 -0
  12. data/lib/rack/auth/abstract/handler.rb +3 -1
  13. data/lib/rack/auth/abstract/request.rb +1 -1
  14. data/lib/rack/auth/basic.rb +6 -4
  15. data/lib/rack/auth/digest/md5.rb +13 -11
  16. data/lib/rack/auth/digest/nonce.rb +5 -3
  17. data/lib/rack/auth/digest/params.rb +4 -2
  18. data/lib/rack/auth/digest/request.rb +5 -3
  19. data/lib/rack/body_proxy.rb +15 -14
  20. data/lib/rack/builder.rb +116 -23
  21. data/lib/rack/cascade.rb +28 -12
  22. data/lib/rack/chunked.rb +68 -20
  23. data/lib/rack/common_logger.rb +37 -25
  24. data/lib/rack/conditional_get.rb +20 -16
  25. data/lib/rack/config.rb +2 -0
  26. data/lib/rack/content_length.rb +8 -7
  27. data/lib/rack/content_type.rb +5 -4
  28. data/lib/rack/core_ext/regexp.rb +14 -0
  29. data/lib/rack/deflater.rb +60 -70
  30. data/lib/rack/directory.rb +84 -64
  31. data/lib/rack/etag.rb +8 -5
  32. data/lib/rack/events.rb +19 -20
  33. data/lib/rack/file.rb +4 -173
  34. data/lib/rack/files.rb +218 -0
  35. data/lib/rack/handler/cgi.rb +2 -3
  36. data/lib/rack/handler/fastcgi.rb +4 -4
  37. data/lib/rack/handler/lsws.rb +3 -3
  38. data/lib/rack/handler/scgi.rb +9 -8
  39. data/lib/rack/handler/thin.rb +3 -3
  40. data/lib/rack/handler/webrick.rb +19 -10
  41. data/lib/rack/handler.rb +7 -2
  42. data/lib/rack/head.rb +1 -1
  43. data/lib/rack/lint.rb +221 -186
  44. data/lib/rack/lobster.rb +10 -10
  45. data/lib/rack/lock.rb +14 -4
  46. data/lib/rack/logger.rb +2 -0
  47. data/lib/rack/media_type.rb +23 -8
  48. data/lib/rack/method_override.rb +13 -4
  49. data/lib/rack/mime.rb +9 -1
  50. data/lib/rack/mock.rb +135 -29
  51. data/lib/rack/multipart/generator.rb +17 -13
  52. data/lib/rack/multipart/parser.rb +85 -68
  53. data/lib/rack/multipart/uploaded_file.rb +15 -7
  54. data/lib/rack/multipart.rb +6 -5
  55. data/lib/rack/null_logger.rb +2 -0
  56. data/lib/rack/query_parser.rb +108 -36
  57. data/lib/rack/recursive.rb +7 -5
  58. data/lib/rack/reloader.rb +8 -4
  59. data/lib/rack/request.rb +232 -60
  60. data/lib/rack/response.rb +127 -44
  61. data/lib/rack/rewindable_input.rb +4 -3
  62. data/lib/rack/runtime.rb +6 -4
  63. data/lib/rack/sendfile.rb +14 -10
  64. data/lib/rack/server.rb +97 -25
  65. data/lib/rack/session/abstract/id.rb +113 -25
  66. data/lib/rack/session/cookie.rb +22 -14
  67. data/lib/rack/session/memcache.rb +4 -87
  68. data/lib/rack/session/pool.rb +24 -10
  69. data/lib/rack/show_exceptions.rb +22 -18
  70. data/lib/rack/show_status.rb +9 -9
  71. data/lib/rack/static.rb +25 -12
  72. data/lib/rack/tempfile_reaper.rb +1 -1
  73. data/lib/rack/urlmap.rb +13 -7
  74. data/lib/rack/utils.rb +135 -123
  75. data/lib/rack/version.rb +29 -0
  76. data/lib/rack.rb +67 -73
  77. data/rack.gemspec +40 -29
  78. metadata +25 -184
  79. data/HISTORY.md +0 -505
  80. data/test/builder/an_underscore_app.rb +0 -5
  81. data/test/builder/anything.rb +0 -5
  82. data/test/builder/comment.ru +0 -4
  83. data/test/builder/end.ru +0 -5
  84. data/test/builder/line.ru +0 -1
  85. data/test/builder/options.ru +0 -2
  86. data/test/cgi/assets/folder/test.js +0 -1
  87. data/test/cgi/assets/fonts/font.eot +0 -1
  88. data/test/cgi/assets/images/image.png +0 -1
  89. data/test/cgi/assets/index.html +0 -1
  90. data/test/cgi/assets/javascripts/app.js +0 -1
  91. data/test/cgi/assets/stylesheets/app.css +0 -1
  92. data/test/cgi/lighttpd.conf +0 -26
  93. data/test/cgi/rackup_stub.rb +0 -6
  94. data/test/cgi/sample_rackup.ru +0 -5
  95. data/test/cgi/test +0 -9
  96. data/test/cgi/test+directory/test+file +0 -1
  97. data/test/cgi/test.fcgi +0 -9
  98. data/test/cgi/test.gz +0 -0
  99. data/test/cgi/test.ru +0 -5
  100. data/test/gemloader.rb +0 -10
  101. data/test/helper.rb +0 -34
  102. data/test/multipart/bad_robots +0 -259
  103. data/test/multipart/binary +0 -0
  104. data/test/multipart/content_type_and_no_filename +0 -6
  105. data/test/multipart/empty +0 -10
  106. data/test/multipart/fail_16384_nofile +0 -814
  107. data/test/multipart/file1.txt +0 -1
  108. data/test/multipart/filename_and_modification_param +0 -7
  109. data/test/multipart/filename_and_no_name +0 -6
  110. data/test/multipart/filename_with_encoded_words +0 -7
  111. data/test/multipart/filename_with_escaped_quotes +0 -6
  112. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  113. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  114. data/test/multipart/filename_with_single_quote +0 -7
  115. data/test/multipart/filename_with_unescaped_percentages +0 -6
  116. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  117. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  118. data/test/multipart/filename_with_unescaped_quotes +0 -6
  119. data/test/multipart/ie +0 -6
  120. data/test/multipart/invalid_character +0 -6
  121. data/test/multipart/mixed_files +0 -21
  122. data/test/multipart/nested +0 -10
  123. data/test/multipart/none +0 -9
  124. data/test/multipart/quoted +0 -15
  125. data/test/multipart/rack-logo.png +0 -0
  126. data/test/multipart/semicolon +0 -6
  127. data/test/multipart/text +0 -15
  128. data/test/multipart/three_files_three_fields +0 -31
  129. data/test/multipart/unity3d_wwwform +0 -11
  130. data/test/multipart/webkit +0 -32
  131. data/test/rackup/config.ru +0 -31
  132. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  133. data/test/spec_auth_basic.rb +0 -89
  134. data/test/spec_auth_digest.rb +0 -260
  135. data/test/spec_body_proxy.rb +0 -85
  136. data/test/spec_builder.rb +0 -233
  137. data/test/spec_cascade.rb +0 -63
  138. data/test/spec_cgi.rb +0 -84
  139. data/test/spec_chunked.rb +0 -103
  140. data/test/spec_common_logger.rb +0 -95
  141. data/test/spec_conditional_get.rb +0 -103
  142. data/test/spec_config.rb +0 -23
  143. data/test/spec_content_length.rb +0 -86
  144. data/test/spec_content_type.rb +0 -46
  145. data/test/spec_deflater.rb +0 -365
  146. data/test/spec_directory.rb +0 -148
  147. data/test/spec_etag.rb +0 -108
  148. data/test/spec_events.rb +0 -133
  149. data/test/spec_fastcgi.rb +0 -85
  150. data/test/spec_file.rb +0 -251
  151. data/test/spec_handler.rb +0 -57
  152. data/test/spec_head.rb +0 -46
  153. data/test/spec_lint.rb +0 -515
  154. data/test/spec_lobster.rb +0 -59
  155. data/test/spec_lock.rb +0 -194
  156. data/test/spec_logger.rb +0 -24
  157. data/test/spec_media_type.rb +0 -42
  158. data/test/spec_method_override.rb +0 -83
  159. data/test/spec_mime.rb +0 -51
  160. data/test/spec_mock.rb +0 -342
  161. data/test/spec_multipart.rb +0 -716
  162. data/test/spec_null_logger.rb +0 -21
  163. data/test/spec_recursive.rb +0 -75
  164. data/test/spec_request.rb +0 -1393
  165. data/test/spec_response.rb +0 -510
  166. data/test/spec_rewindable_input.rb +0 -128
  167. data/test/spec_runtime.rb +0 -50
  168. data/test/spec_sendfile.rb +0 -125
  169. data/test/spec_server.rb +0 -193
  170. data/test/spec_session_abstract_id.rb +0 -31
  171. data/test/spec_session_abstract_session_hash.rb +0 -28
  172. data/test/spec_session_cookie.rb +0 -442
  173. data/test/spec_session_memcache.rb +0 -320
  174. data/test/spec_session_pool.rb +0 -210
  175. data/test/spec_show_exceptions.rb +0 -80
  176. data/test/spec_show_status.rb +0 -104
  177. data/test/spec_static.rb +0 -184
  178. data/test/spec_tempfile_reaper.rb +0 -64
  179. data/test/spec_thin.rb +0 -96
  180. data/test/spec_urlmap.rb +0 -237
  181. data/test/spec_utils.rb +0 -742
  182. data/test/spec_version.rb +0 -11
  183. data/test/spec_webrick.rb +0 -208
  184. data/test/static/another/index.html +0 -1
  185. data/test/static/foo.html +0 -1
  186. data/test/static/index.html +0 -1
  187. data/test/testrequest.rb +0 -78
  188. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  189. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -1,16 +1,43 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # AUTHOR: blink <blinketje@gmail.com>; blink#ruby-lang@irc.freenode.net
2
4
  # bugrep: Andreas Zehnder
3
5
 
4
- require 'rack'
6
+ require_relative '../../../rack'
5
7
  require 'time'
6
- require 'rack/request'
7
- require 'rack/response'
8
8
  require 'securerandom'
9
+ require 'digest/sha2'
9
10
 
10
11
  module Rack
11
12
 
12
13
  module Session
13
14
 
15
+ class SessionId
16
+ ID_VERSION = 2
17
+
18
+ attr_reader :public_id
19
+
20
+ def initialize(public_id)
21
+ @public_id = public_id
22
+ end
23
+
24
+ def private_id
25
+ "#{ID_VERSION}::#{hash_sid(public_id)}"
26
+ end
27
+
28
+ alias :cookie_value :public_id
29
+ alias :to_s :public_id
30
+
31
+ def empty?; false; end
32
+ def inspect; public_id.inspect; end
33
+
34
+ private
35
+
36
+ def hash_sid(sid)
37
+ Digest::SHA256.hexdigest(sid)
38
+ end
39
+ end
40
+
14
41
  module Abstract
15
42
  # SessionHash is responsible to lazily load the session from store.
16
43
 
@@ -18,6 +45,8 @@ module Rack
18
45
  include Enumerable
19
46
  attr_writer :id
20
47
 
48
+ Unspecified = Object.new
49
+
21
50
  def self.find(req)
22
51
  req.get_header RACK_SESSION
23
52
  end
@@ -54,7 +83,20 @@ module Rack
54
83
  load_for_read!
55
84
  @data[key.to_s]
56
85
  end
57
- alias :fetch :[]
86
+
87
+ def dig(key, *keys)
88
+ load_for_read!
89
+ @data.dig(key.to_s, *keys)
90
+ end
91
+
92
+ def fetch(key, default = Unspecified, &block)
93
+ load_for_read!
94
+ if default == Unspecified
95
+ @data.fetch(key.to_s, &block)
96
+ else
97
+ @data.fetch(key.to_s, default, &block)
98
+ end
99
+ end
58
100
 
59
101
  def has_key?(key)
60
102
  load_for_read!
@@ -150,8 +192,9 @@ module Rack
150
192
  end
151
193
 
152
194
  def stringify_keys(other)
195
+ # Use transform_keys after dropping Ruby 2.4 support
153
196
  hash = {}
154
- other.each do |key, value|
197
+ other.to_hash.each do |key, value|
155
198
  hash[key.to_s] = value
156
199
  end
157
200
  hash
@@ -160,14 +203,14 @@ module Rack
160
203
 
161
204
  # ID sets up a basic framework for implementing an id based sessioning
162
205
  # service. Cookies sent to the client for maintaining sessions will only
163
- # contain an id reference. Only #find_session and #write_session are
164
- # required to be overwritten.
206
+ # contain an id reference. Only #find_session, #write_session and
207
+ # #delete_session are required to be overwritten.
165
208
  #
166
209
  # All parameters are optional.
167
210
  # * :key determines the name of the cookie, by default it is
168
211
  # 'rack.session'
169
212
  # * :path, :domain, :expire_after, :secure, and :httponly set the related
170
- # cookie options as by Rack::Response#add_cookie
213
+ # cookie options as by Rack::Response#set_cookie
171
214
  # * :skip will not a set a cookie in the response nor update the session state
172
215
  # * :defer will not set a cookie in the response but still update the session
173
216
  # state if it is used with a backend
@@ -189,26 +232,27 @@ module Rack
189
232
 
190
233
  class Persisted
191
234
  DEFAULT_OPTIONS = {
192
- :key => RACK_SESSION,
193
- :path => '/',
194
- :domain => nil,
195
- :expire_after => nil,
196
- :secure => false,
197
- :httponly => true,
198
- :defer => false,
199
- :renew => false,
200
- :sidbits => 128,
201
- :cookie_only => true,
202
- :secure_random => ::SecureRandom
203
- }
235
+ key: RACK_SESSION,
236
+ path: '/',
237
+ domain: nil,
238
+ expire_after: nil,
239
+ secure: false,
240
+ httponly: true,
241
+ defer: false,
242
+ renew: false,
243
+ sidbits: 128,
244
+ cookie_only: true,
245
+ secure_random: ::SecureRandom
246
+ }.freeze
204
247
 
205
248
  attr_reader :key, :default_options, :sid_secure
206
249
 
207
- def initialize(app, options={})
250
+ def initialize(app, options = {})
208
251
  @app = app
209
252
  @default_options = self.class::DEFAULT_OPTIONS.merge(options)
210
253
  @key = @default_options.delete(:key)
211
254
  @cookie_only = @default_options.delete(:cookie_only)
255
+ @same_site = @default_options.delete(:same_site)
212
256
  initialize_sid
213
257
  end
214
258
 
@@ -216,7 +260,7 @@ module Rack
216
260
  context(env)
217
261
  end
218
262
 
219
- def context(env, app=@app)
263
+ def context(env, app = @app)
220
264
  req = make_request env
221
265
  prepare_session(req)
222
266
  status, headers, body = app.call(req.env)
@@ -339,7 +383,7 @@ module Rack
339
383
 
340
384
  session.send(:load!) unless loaded_session?(session)
341
385
  session_id ||= session.id
342
- session_data = session.to_hash.delete_if { |k,v| v.nil? }
386
+ session_data = session.to_hash.delete_if { |k, v| v.nil? }
343
387
 
344
388
  if not data = write_session(req, session_id, session_data, options)
345
389
  req.get_header(RACK_ERRORS).puts("Warning! #{self.class.name} failed to save session. Content dropped.")
@@ -347,14 +391,24 @@ module Rack
347
391
  req.get_header(RACK_ERRORS).puts("Deferring cookie for #{session_id}") if $VERBOSE
348
392
  else
349
393
  cookie = Hash.new
350
- cookie[:value] = data
394
+ cookie[:value] = cookie_value(data)
351
395
  cookie[:expires] = Time.now + options[:expire_after] if options[:expire_after]
352
396
  cookie[:expires] = Time.now + options[:max_age] if options[:max_age]
397
+
398
+ if @same_site.respond_to? :call
399
+ cookie[:same_site] = @same_site.call(req, res)
400
+ else
401
+ cookie[:same_site] = @same_site
402
+ end
353
403
  set_cookie(req, res, cookie.merge!(options))
354
404
  end
355
405
  end
356
406
  public :commit_session
357
407
 
408
+ def cookie_value(data)
409
+ data
410
+ end
411
+
358
412
  # Sets the cookie back to the client with session id. We skip the cookie
359
413
  # setting if the value didn't change (sid is the same) or expires was given.
360
414
 
@@ -396,9 +450,43 @@ module Rack
396
450
  end
397
451
  end
398
452
 
453
+ class PersistedSecure < Persisted
454
+ class SecureSessionHash < SessionHash
455
+ def [](key)
456
+ if key == "session_id"
457
+ load_for_read!
458
+ id.public_id if id
459
+ else
460
+ super
461
+ end
462
+ end
463
+ end
464
+
465
+ def generate_sid(*)
466
+ public_id = super
467
+
468
+ SessionId.new(public_id)
469
+ end
470
+
471
+ def extract_session_id(*)
472
+ public_id = super
473
+ public_id && SessionId.new(public_id)
474
+ end
475
+
476
+ private
477
+
478
+ def session_class
479
+ SecureSessionHash
480
+ end
481
+
482
+ def cookie_value(data)
483
+ data.cookie_value
484
+ end
485
+ end
486
+
399
487
  class ID < Persisted
400
488
  def self.inherited(klass)
401
- k = klass.ancestors.find { |kl| kl.superclass == ID }
489
+ k = klass.ancestors.find { |kl| kl.respond_to?(:superclass) && kl.superclass == ID }
402
490
  unless k.instance_variable_defined?(:"@_rack_warned")
403
491
  warn "#{klass} is inheriting from #{ID}. Inheriting from #{ID} is deprecated, please inherit from #{Persisted} instead" if $VERBOSE
404
492
  k.instance_variable_set(:"@_rack_warned", true)
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'openssl'
2
4
  require 'zlib'
3
- require 'rack/request'
4
- require 'rack/response'
5
- require 'rack/session/abstract/id'
5
+ require_relative 'abstract/id'
6
6
  require 'json'
7
+ require 'delegate'
7
8
 
8
9
  module Rack
9
10
 
@@ -45,15 +46,15 @@ module Rack
45
46
  # })
46
47
  #
47
48
 
48
- class Cookie < Abstract::Persisted
49
+ class Cookie < Abstract::PersistedSecure
49
50
  # Encode session cookies as Base64
50
51
  class Base64
51
52
  def encode(str)
52
- [str].pack('m')
53
+ [str].pack("m0")
53
54
  end
54
55
 
55
56
  def decode(str)
56
- str.unpack('m').first
57
+ str.unpack("m").first
57
58
  end
58
59
 
59
60
  # Encode session cookies as Marshaled Base64 data
@@ -103,7 +104,7 @@ module Rack
103
104
 
104
105
  attr_reader :coder
105
106
 
106
- def initialize(app, options={})
107
+ def initialize(app, options = {})
107
108
  @secrets = options.values_at(:secret, :old_secret).compact
108
109
  @hmac = options.fetch(:hmac, OpenSSL::Digest::SHA1)
109
110
 
@@ -116,8 +117,8 @@ module Rack
116
117
 
117
118
  Called from: #{caller[0]}.
118
119
  MSG
119
- @coder = options[:coder] ||= Base64::Marshal.new
120
- super(app, options.merge!(:cookie_only => true))
120
+ @coder = options[:coder] ||= Base64::Marshal.new
121
+ super(app, options.merge!(cookie_only: true))
121
122
  end
122
123
 
123
124
  private
@@ -137,9 +138,7 @@ module Rack
137
138
  session_data = request.cookies[@key]
138
139
 
139
140
  if @secrets.size > 0 && session_data
140
- digest, session_data = session_data.reverse.split("--", 2)
141
- digest.reverse! if digest
142
- session_data.reverse! if session_data
141
+ session_data, _, digest = session_data.rpartition('--')
143
142
  session_data = nil unless digest_match?(session_data, digest)
144
143
  end
145
144
 
@@ -147,12 +146,21 @@ module Rack
147
146
  end
148
147
  end
149
148
 
150
- def persistent_session_id!(data, sid=nil)
149
+ def persistent_session_id!(data, sid = nil)
151
150
  data ||= {}
152
151
  data["session_id"] ||= sid || generate_sid
153
152
  data
154
153
  end
155
154
 
155
+ class SessionId < DelegateClass(Session::SessionId)
156
+ attr_reader :cookie_value
157
+
158
+ def initialize(session_id, cookie_value)
159
+ super(session_id)
160
+ @cookie_value = cookie_value
161
+ end
162
+ end
163
+
156
164
  def write_session(req, session_id, session, options)
157
165
  session = session.merge("session_id" => session_id)
158
166
  session_data = coder.encode(session)
@@ -165,7 +173,7 @@ module Rack
165
173
  req.get_header(RACK_ERRORS).puts("Warning! Rack::Session::Cookie data size exceeds 4K.")
166
174
  nil
167
175
  else
168
- session_data
176
+ SessionId.new(session_id, session_data)
169
177
  end
170
178
  end
171
179
 
@@ -1,93 +1,10 @@
1
- # AUTHOR: blink <blinketje@gmail.com>; blink#ruby-lang@irc.freenode.net
1
+ # frozen_string_literal: true
2
2
 
3
- require 'rack/session/abstract/id'
4
- require 'memcache'
3
+ require 'rack/session/dalli'
5
4
 
6
5
  module Rack
7
6
  module Session
8
- # Rack::Session::Memcache provides simple cookie based session management.
9
- # Session data is stored in memcached. The corresponding session key is
10
- # maintained in the cookie.
11
- # You may treat Session::Memcache as you would Session::Pool with the
12
- # following caveats.
13
- #
14
- # * Setting :expire_after to 0 would note to the Memcache server to hang
15
- # onto the session data until it would drop it according to it's own
16
- # specifications. However, the cookie sent to the client would expire
17
- # immediately.
18
- #
19
- # Note that memcache does drop data before it may be listed to expire. For
20
- # a full description of behaviour, please see memcache's documentation.
21
-
22
- class Memcache < Abstract::ID
23
- attr_reader :mutex, :pool
24
-
25
- DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge \
26
- :namespace => 'rack:session',
27
- :memcache_server => 'localhost:11211'
28
-
29
- def initialize(app, options={})
30
- super
31
-
32
- @mutex = Mutex.new
33
- mserv = @default_options[:memcache_server]
34
- mopts = @default_options.reject{|k,v| !MemCache::DEFAULT_OPTIONS.include? k }
35
-
36
- @pool = options[:cache] || MemCache.new(mserv, mopts)
37
- unless @pool.active? and @pool.servers.any?(&:alive?)
38
- raise 'No memcache servers'
39
- end
40
- end
41
-
42
- def generate_sid
43
- loop do
44
- sid = super
45
- break sid unless @pool.get(sid, true)
46
- end
47
- end
48
-
49
- def get_session(env, sid)
50
- with_lock(env) do
51
- unless sid and session = @pool.get(sid)
52
- sid, session = generate_sid, {}
53
- unless /^STORED/ =~ @pool.add(sid, session)
54
- raise "Session collision on '#{sid.inspect}'"
55
- end
56
- end
57
- [sid, session]
58
- end
59
- end
60
-
61
- def set_session(env, session_id, new_session, options)
62
- expiry = options[:expire_after]
63
- expiry = expiry.nil? ? 0 : expiry + 1
64
-
65
- with_lock(env) do
66
- @pool.set session_id, new_session, expiry
67
- session_id
68
- end
69
- end
70
-
71
- def destroy_session(env, session_id, options)
72
- with_lock(env) do
73
- @pool.delete(session_id)
74
- generate_sid unless options[:drop]
75
- end
76
- end
77
-
78
- def with_lock(env)
79
- @mutex.lock if env[RACK_MULTITHREAD]
80
- yield
81
- rescue MemCache::MemCacheError, Errno::ECONNREFUSED
82
- if $VERBOSE
83
- warn "#{self} is unable to find memcached server."
84
- warn $!.inspect
85
- end
86
- raise
87
- ensure
88
- @mutex.unlock if @mutex.locked?
89
- end
90
-
91
- end
7
+ warn "Rack::Session::Memcache is deprecated, please use Rack::Session::Dalli from 'dalli' gem instead."
8
+ Memcache = Dalli
92
9
  end
93
10
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # AUTHOR: blink <blinketje@gmail.com>; blink#ruby-lang@irc.freenode.net
2
4
  # THANKS:
3
5
  # apeiros, for session id generation, expiry setup, and threadiness
4
6
  # sergio, threadiness and bugreps
5
7
 
6
- require 'rack/session/abstract/id'
8
+ require_relative 'abstract/id'
7
9
  require 'thread'
8
10
 
9
11
  module Rack
@@ -24,11 +26,11 @@ module Rack
24
26
  # )
25
27
  # Rack::Handler::WEBrick.run sessioned
26
28
 
27
- class Pool < Abstract::Persisted
29
+ class Pool < Abstract::PersistedSecure
28
30
  attr_reader :mutex, :pool
29
- DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge :drop => false
31
+ DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge drop: false
30
32
 
31
- def initialize(app, options={})
33
+ def initialize(app, options = {})
32
34
  super
33
35
  @pool = Hash.new
34
36
  @mutex = Mutex.new
@@ -37,15 +39,15 @@ module Rack
37
39
  def generate_sid
38
40
  loop do
39
41
  sid = super
40
- break sid unless @pool.key? sid
42
+ break sid unless @pool.key? sid.private_id
41
43
  end
42
44
  end
43
45
 
44
46
  def find_session(req, sid)
45
47
  with_lock(req) do
46
- unless sid and session = @pool[sid]
48
+ unless sid and session = get_session_with_fallback(sid)
47
49
  sid, session = generate_sid, {}
48
- @pool.store sid, session
50
+ @pool.store sid.private_id, session
49
51
  end
50
52
  [sid, session]
51
53
  end
@@ -53,15 +55,21 @@ module Rack
53
55
 
54
56
  def write_session(req, session_id, new_session, options)
55
57
  with_lock(req) do
56
- @pool.store session_id, new_session
58
+ return false unless get_session_with_fallback(session_id)
59
+ @pool.store session_id.private_id, new_session
57
60
  session_id
58
61
  end
59
62
  end
60
63
 
61
64
  def delete_session(req, session_id, options)
62
65
  with_lock(req) do
63
- @pool.delete(session_id)
64
- generate_sid unless options[:drop]
66
+ @pool.delete(session_id.public_id)
67
+ @pool.delete(session_id.private_id)
68
+ unless options[:drop]
69
+ sid = generate_sid
70
+ @pool.store(sid.private_id, {})
71
+ sid
72
+ end
65
73
  end
66
74
  end
67
75
 
@@ -71,6 +79,12 @@ module Rack
71
79
  ensure
72
80
  @mutex.unlock if @mutex.locked?
73
81
  end
82
+
83
+ private
84
+
85
+ def get_session_with_fallback(sid)
86
+ @pool[sid.private_id] || @pool[sid.public_id]
87
+ end
74
88
  end
75
89
  end
76
90
  end
@@ -1,7 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ostruct'
2
4
  require 'erb'
3
- require 'rack/request'
4
- require 'rack/utils'
5
5
 
6
6
  module Rack
7
7
  # Rack::ShowExceptions catches all exceptions raised from the app it
@@ -46,7 +46,7 @@ module Rack
46
46
  end
47
47
 
48
48
  def prefers_plaintext?(env)
49
- !accepts_html(env)
49
+ !accepts_html?(env)
50
50
  end
51
51
 
52
52
  def accepts_html?(env)
@@ -55,7 +55,7 @@ module Rack
55
55
  private :accepts_html?
56
56
 
57
57
  def dump_exception(exception)
58
- string = "#{exception.class}: #{exception.message}\n"
58
+ string = "#{exception.class}: #{exception.message}\n".dup
59
59
  string << exception.backtrace.map { |l| "\t#{l}" }.join("\n")
60
60
  string
61
61
  end
@@ -63,12 +63,12 @@ module Rack
63
63
  def pretty(env, exception)
64
64
  req = Rack::Request.new(env)
65
65
 
66
- # This double assignment is to prevent an "unused variable" warning on
67
- # Ruby 1.9.3. Yes, it is dumb, but I don't like Ruby yelling at me.
66
+ # This double assignment is to prevent an "unused variable" warning.
67
+ # Yes, it is dumb, but I don't like Ruby yelling at me.
68
68
  path = path = (req.script_name + req.path_info).squeeze("/")
69
69
 
70
- # This double assignment is to prevent an "unused variable" warning on
71
- # Ruby 1.9.3. Yes, it is dumb, but I don't like Ruby yelling at me.
70
+ # This double assignment is to prevent an "unused variable" warning.
71
+ # Yes, it is dumb, but I don't like Ruby yelling at me.
72
72
  frames = frames = exception.backtrace.map { |line|
73
73
  frame = OpenStruct.new
74
74
  if line =~ /(.*?):(\d+)(:in `(.*)')?/
@@ -77,13 +77,13 @@ module Rack
77
77
  frame.function = $4
78
78
 
79
79
  begin
80
- lineno = frame.lineno-1
80
+ lineno = frame.lineno - 1
81
81
  lines = ::File.readlines(frame.filename)
82
- frame.pre_context_lineno = [lineno-CONTEXT, 0].max
82
+ frame.pre_context_lineno = [lineno - CONTEXT, 0].max
83
83
  frame.pre_context = lines[frame.pre_context_lineno...lineno]
84
84
  frame.context_line = lines[lineno].chomp
85
- frame.post_context_lineno = [lineno+CONTEXT, lines.size].min
86
- frame.post_context = lines[lineno+1..frame.post_context_lineno]
85
+ frame.post_context_lineno = [lineno + CONTEXT, lines.size].min
86
+ frame.post_context = lines[lineno + 1..frame.post_context_lineno]
87
87
  rescue
88
88
  end
89
89
 
@@ -93,7 +93,11 @@ module Rack
93
93
  end
94
94
  }.compact
95
95
 
96
- TEMPLATE.result(binding)
96
+ template.result(binding)
97
+ end
98
+
99
+ def template
100
+ TEMPLATE
97
101
  end
98
102
 
99
103
  def h(obj) # :nodoc:
@@ -107,8 +111,8 @@ module Rack
107
111
 
108
112
  # :stopdoc:
109
113
 
110
- # adapted from Django <djangoproject.com>
111
- # Copyright (c) 2005, the Lawrence Journal-World
114
+ # adapted from Django <www.djangoproject.com>
115
+ # Copyright (c) Django Software Foundation and individual contributors.
112
116
  # Used under the modified BSD license:
113
117
  # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
114
118
  TEMPLATE = ERB.new(<<-'HTML'.gsub(/^ /, ''))
@@ -307,7 +311,7 @@ module Rack
307
311
  <% end %>
308
312
 
309
313
  <h3 id="post-info">POST</h3>
310
- <% if req.POST and not req.POST.empty? %>
314
+ <% if ((req.POST and not req.POST.empty?) rescue (no_post_data = "Invalid POST data"; nil)) %>
311
315
  <table class="req">
312
316
  <thead>
313
317
  <tr>
@@ -325,7 +329,7 @@ module Rack
325
329
  </tbody>
326
330
  </table>
327
331
  <% else %>
328
- <p>No POST data.</p>
332
+ <p><%= no_post_data || "No POST data" %>.</p>
329
333
  <% end %>
330
334
 
331
335
 
@@ -363,7 +367,7 @@ module Rack
363
367
  <% env.sort_by { |k, v| k.to_s }.each { |key, val| %>
364
368
  <tr>
365
369
  <td><%=h key %></td>
366
- <td class="code"><div><%=h val %></div></td>
370
+ <td class="code"><div><%=h val.inspect %></div></td>
367
371
  </tr>
368
372
  <% } %>
369
373
  </tbody>
@@ -1,6 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'erb'
2
- require 'rack/request'
3
- require 'rack/utils'
4
4
 
5
5
  module Rack
6
6
  # Rack::ShowStatus catches all empty responses and replaces them
@@ -18,19 +18,19 @@ module Rack
18
18
 
19
19
  def call(env)
20
20
  status, headers, body = @app.call(env)
21
- headers = Utils::HeaderHash.new(headers)
21
+ headers = Utils::HeaderHash[headers]
22
22
  empty = headers[CONTENT_LENGTH].to_i <= 0
23
23
 
24
24
  # client or server error, or explicit message
25
25
  if (status.to_i >= 400 && empty) || env[RACK_SHOWSTATUS_DETAIL]
26
- # This double assignment is to prevent an "unused variable" warning on
27
- # Ruby 1.9.3. Yes, it is dumb, but I don't like Ruby yelling at me.
26
+ # This double assignment is to prevent an "unused variable" warning.
27
+ # Yes, it is dumb, but I don't like Ruby yelling at me.
28
28
  req = req = Rack::Request.new(env)
29
29
 
30
30
  message = Rack::Utils::HTTP_STATUS_CODES[status.to_i] || status.to_s
31
31
 
32
- # This double assignment is to prevent an "unused variable" warning on
33
- # Ruby 1.9.3. Yes, it is dumb, but I don't like Ruby yelling at me.
32
+ # This double assignment is to prevent an "unused variable" warning.
33
+ # Yes, it is dumb, but I don't like Ruby yelling at me.
34
34
  detail = detail = env[RACK_SHOWSTATUS_DETAIL] || message
35
35
 
36
36
  body = @template.result(binding)
@@ -52,8 +52,8 @@ module Rack
52
52
 
53
53
  # :stopdoc:
54
54
 
55
- # adapted from Django <djangoproject.com>
56
- # Copyright (c) 2005, the Lawrence Journal-World
55
+ # adapted from Django <www.djangoproject.com>
56
+ # Copyright (c) Django Software Foundation and individual contributors.
57
57
  # Used under the modified BSD license:
58
58
  # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
59
59
  TEMPLATE = <<'HTML'