rack 2.0.9.3 → 2.1.4.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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +92 -0
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +76 -116
  5. data/Rakefile +25 -18
  6. data/SPEC +9 -9
  7. data/bin/rackup +1 -0
  8. data/example/lobster.ru +2 -0
  9. data/example/protectedlobster.rb +3 -1
  10. data/example/protectedlobster.ru +2 -0
  11. data/lib/rack/auth/abstract/handler.rb +3 -1
  12. data/lib/rack/auth/abstract/request.rb +2 -0
  13. data/lib/rack/auth/basic.rb +4 -1
  14. data/lib/rack/auth/digest/md5.rb +9 -7
  15. data/lib/rack/auth/digest/nonce.rb +6 -3
  16. data/lib/rack/auth/digest/params.rb +4 -2
  17. data/lib/rack/auth/digest/request.rb +2 -0
  18. data/lib/rack/body_proxy.rb +3 -6
  19. data/lib/rack/builder.rb +39 -15
  20. data/lib/rack/cascade.rb +6 -5
  21. data/lib/rack/chunked.rb +29 -6
  22. data/lib/rack/common_logger.rb +9 -8
  23. data/lib/rack/conditional_get.rb +3 -1
  24. data/lib/rack/config.rb +2 -0
  25. data/lib/rack/content_length.rb +3 -1
  26. data/lib/rack/content_type.rb +3 -1
  27. data/lib/rack/core_ext/regexp.rb +14 -0
  28. data/lib/rack/deflater.rb +32 -17
  29. data/lib/rack/directory.rb +19 -16
  30. data/lib/rack/etag.rb +3 -1
  31. data/lib/rack/events.rb +5 -3
  32. data/lib/rack/file.rb +4 -173
  33. data/lib/rack/files.rb +178 -0
  34. data/lib/rack/handler/cgi.rb +3 -1
  35. data/lib/rack/handler/fastcgi.rb +4 -2
  36. data/lib/rack/handler/lsws.rb +3 -1
  37. data/lib/rack/handler/scgi.rb +9 -6
  38. data/lib/rack/handler/thin.rb +3 -1
  39. data/lib/rack/handler/webrick.rb +4 -2
  40. data/lib/rack/handler.rb +7 -2
  41. data/lib/rack/head.rb +2 -0
  42. data/lib/rack/lint.rb +14 -11
  43. data/lib/rack/lobster.rb +7 -5
  44. data/lib/rack/lock.rb +2 -0
  45. data/lib/rack/logger.rb +2 -0
  46. data/lib/rack/media_type.rb +10 -5
  47. data/lib/rack/method_override.rb +4 -2
  48. data/lib/rack/mime.rb +9 -1
  49. data/lib/rack/mock.rb +74 -15
  50. data/lib/rack/multipart/generator.rb +6 -7
  51. data/lib/rack/multipart/parser.rb +50 -45
  52. data/lib/rack/multipart/uploaded_file.rb +2 -0
  53. data/lib/rack/multipart.rb +3 -1
  54. data/lib/rack/null_logger.rb +2 -0
  55. data/lib/rack/query_parser.rb +51 -25
  56. data/lib/rack/recursive.rb +7 -5
  57. data/lib/rack/reloader.rb +10 -4
  58. data/lib/rack/request.rb +79 -26
  59. data/lib/rack/response.rb +71 -31
  60. data/lib/rack/rewindable_input.rb +4 -2
  61. data/lib/rack/runtime.rb +4 -2
  62. data/lib/rack/sendfile.rb +15 -8
  63. data/lib/rack/server.rb +88 -18
  64. data/lib/rack/session/abstract/id.rb +30 -20
  65. data/lib/rack/session/cookie.rb +10 -9
  66. data/lib/rack/session/memcache.rb +4 -93
  67. data/lib/rack/session/pool.rb +4 -2
  68. data/lib/rack/show_exceptions.rb +15 -9
  69. data/lib/rack/show_status.rb +4 -2
  70. data/lib/rack/static.rb +15 -10
  71. data/lib/rack/tempfile_reaper.rb +2 -0
  72. data/lib/rack/urlmap.rb +11 -2
  73. data/lib/rack/utils.rb +58 -71
  74. data/lib/rack.rb +63 -60
  75. data/rack.gemspec +17 -7
  76. metadata +28 -170
  77. data/HISTORY.md +0 -520
  78. data/test/builder/an_underscore_app.rb +0 -5
  79. data/test/builder/anything.rb +0 -5
  80. data/test/builder/comment.ru +0 -4
  81. data/test/builder/end.ru +0 -5
  82. data/test/builder/line.ru +0 -1
  83. data/test/builder/options.ru +0 -2
  84. data/test/cgi/assets/folder/test.js +0 -1
  85. data/test/cgi/assets/fonts/font.eot +0 -1
  86. data/test/cgi/assets/images/image.png +0 -1
  87. data/test/cgi/assets/index.html +0 -1
  88. data/test/cgi/assets/javascripts/app.js +0 -1
  89. data/test/cgi/assets/stylesheets/app.css +0 -1
  90. data/test/cgi/lighttpd.conf +0 -26
  91. data/test/cgi/rackup_stub.rb +0 -6
  92. data/test/cgi/sample_rackup.ru +0 -5
  93. data/test/cgi/test +0 -9
  94. data/test/cgi/test+directory/test+file +0 -1
  95. data/test/cgi/test.fcgi +0 -9
  96. data/test/cgi/test.gz +0 -0
  97. data/test/cgi/test.ru +0 -5
  98. data/test/gemloader.rb +0 -10
  99. data/test/helper.rb +0 -34
  100. data/test/multipart/bad_robots +0 -259
  101. data/test/multipart/binary +0 -0
  102. data/test/multipart/content_type_and_no_filename +0 -6
  103. data/test/multipart/empty +0 -10
  104. data/test/multipart/fail_16384_nofile +0 -814
  105. data/test/multipart/file1.txt +0 -1
  106. data/test/multipart/filename_and_modification_param +0 -7
  107. data/test/multipart/filename_and_no_name +0 -6
  108. data/test/multipart/filename_with_encoded_words +0 -7
  109. data/test/multipart/filename_with_escaped_quotes +0 -6
  110. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  111. data/test/multipart/filename_with_null_byte +0 -7
  112. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  113. data/test/multipart/filename_with_single_quote +0 -7
  114. data/test/multipart/filename_with_unescaped_percentages +0 -6
  115. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  116. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  117. data/test/multipart/filename_with_unescaped_quotes +0 -6
  118. data/test/multipart/ie +0 -6
  119. data/test/multipart/invalid_character +0 -6
  120. data/test/multipart/mixed_files +0 -21
  121. data/test/multipart/nested +0 -10
  122. data/test/multipart/none +0 -9
  123. data/test/multipart/quoted +0 -15
  124. data/test/multipart/rack-logo.png +0 -0
  125. data/test/multipart/semicolon +0 -6
  126. data/test/multipart/text +0 -15
  127. data/test/multipart/three_files_three_fields +0 -31
  128. data/test/multipart/unity3d_wwwform +0 -11
  129. data/test/multipart/webkit +0 -32
  130. data/test/rackup/config.ru +0 -31
  131. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  132. data/test/spec_auth_basic.rb +0 -89
  133. data/test/spec_auth_digest.rb +0 -260
  134. data/test/spec_body_proxy.rb +0 -85
  135. data/test/spec_builder.rb +0 -233
  136. data/test/spec_cascade.rb +0 -63
  137. data/test/spec_cgi.rb +0 -84
  138. data/test/spec_chunked.rb +0 -103
  139. data/test/spec_common_logger.rb +0 -107
  140. data/test/spec_conditional_get.rb +0 -103
  141. data/test/spec_config.rb +0 -23
  142. data/test/spec_content_length.rb +0 -86
  143. data/test/spec_content_type.rb +0 -46
  144. data/test/spec_deflater.rb +0 -375
  145. data/test/spec_directory.rb +0 -148
  146. data/test/spec_etag.rb +0 -108
  147. data/test/spec_events.rb +0 -133
  148. data/test/spec_fastcgi.rb +0 -85
  149. data/test/spec_file.rb +0 -264
  150. data/test/spec_handler.rb +0 -57
  151. data/test/spec_head.rb +0 -46
  152. data/test/spec_lint.rb +0 -520
  153. data/test/spec_lobster.rb +0 -59
  154. data/test/spec_lock.rb +0 -204
  155. data/test/spec_logger.rb +0 -24
  156. data/test/spec_media_type.rb +0 -42
  157. data/test/spec_method_override.rb +0 -110
  158. data/test/spec_mime.rb +0 -51
  159. data/test/spec_mock.rb +0 -359
  160. data/test/spec_multipart.rb +0 -721
  161. data/test/spec_null_logger.rb +0 -21
  162. data/test/spec_recursive.rb +0 -75
  163. data/test/spec_request.rb +0 -1423
  164. data/test/spec_response.rb +0 -528
  165. data/test/spec_rewindable_input.rb +0 -128
  166. data/test/spec_runtime.rb +0 -50
  167. data/test/spec_sendfile.rb +0 -125
  168. data/test/spec_server.rb +0 -193
  169. data/test/spec_session_abstract_id.rb +0 -31
  170. data/test/spec_session_abstract_session_hash.rb +0 -45
  171. data/test/spec_session_cookie.rb +0 -442
  172. data/test/spec_session_memcache.rb +0 -357
  173. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  174. data/test/spec_session_pool.rb +0 -247
  175. data/test/spec_show_exceptions.rb +0 -93
  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 -206
  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
data/lib/rack/sendfile.rb CHANGED
@@ -1,4 +1,6 @@
1
- require 'rack/file'
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack/files'
2
4
  require 'rack/body_proxy'
3
5
 
4
6
  module Rack
@@ -14,7 +16,7 @@ module Rack
14
16
  #
15
17
  # In order to take advantage of this middleware, the response body must
16
18
  # respond to +to_path+ and the request must include an X-Sendfile-Type
17
- # header. Rack::File and other components implement +to_path+ so there's
19
+ # header. Rack::Files and other components implement +to_path+ so there's
18
20
  # rarely anything you need to do in your application. The X-Sendfile-Type
19
21
  # header is typically set in your web servers configuration. The following
20
22
  # sections attempt to document
@@ -53,7 +55,7 @@ module Rack
53
55
  # that it maps to. The middleware performs a simple substitution on the
54
56
  # resulting path.
55
57
  #
56
- # See Also: http://wiki.codemongers.com/NginxXSendfile
58
+ # See Also: https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile
57
59
  #
58
60
  # === lighttpd
59
61
  #
@@ -99,7 +101,7 @@ module Rack
99
101
  # will be matched with case indifference.
100
102
 
101
103
  class Sendfile
102
- def initialize(app, variation=nil, mappings=[])
104
+ def initialize(app, variation = nil, mappings = [])
103
105
  @app = app
104
106
  @variation = variation
105
107
  @mappings = mappings.map do |internal, external|
@@ -115,7 +117,8 @@ module Rack
115
117
  path = ::File.expand_path(body.to_path)
116
118
  if url = map_accel_path(env, path)
117
119
  headers[CONTENT_LENGTH] = '0'
118
- headers[type] = url
120
+ # '?' must be percent-encoded because it is not query string but a part of path
121
+ headers[type] = ::Rack::Utils.escape_path(url).gsub('?', '%3F')
119
122
  obody = body
120
123
  body = Rack::BodyProxy.new([]) do
121
124
  obody.close if obody.respond_to?(:close)
@@ -147,11 +150,15 @@ module Rack
147
150
  end
148
151
 
149
152
  def map_accel_path(env, path)
150
- if mapping = @mappings.find { |internal,_| internal =~ path }
153
+ if mapping = @mappings.find { |internal, _| internal =~ path }
151
154
  path.sub(*mapping)
152
155
  elsif mapping = env['HTTP_X_ACCEL_MAPPING']
153
- internal, external = mapping.split('=', 2).map(&:strip)
154
- path.sub(/^#{internal}/i, external)
156
+ mapping.split(',').map(&:strip).each do |m|
157
+ internal, external = m.split('=', 2).map(&:strip)
158
+ new_path = path.sub(/^#{internal}/i, external)
159
+ return new_path unless path == new_path
160
+ end
161
+ path
155
162
  end
156
163
  end
157
164
  end
data/lib/rack/server.rb CHANGED
@@ -1,10 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'optparse'
2
4
  require 'fileutils'
3
5
 
6
+ require_relative 'core_ext/regexp'
4
7
 
5
8
  module Rack
6
9
 
7
10
  class Server
11
+ using ::Rack::RegexpExtensions
8
12
 
9
13
  class Options
10
14
  def parse!(args)
@@ -21,10 +25,6 @@ module Rack
21
25
  lineno += 1
22
26
  }
23
27
 
24
- opts.on("-b", "--builder BUILDER_LINE", "evaluate a BUILDER_LINE of code as a builder script") { |line|
25
- options[:builder] = line
26
- }
27
-
28
28
  opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") {
29
29
  options[:debug] = true
30
30
  }
@@ -47,7 +47,11 @@ module Rack
47
47
 
48
48
  opts.separator ""
49
49
  opts.separator "Rack options:"
50
- opts.on("-s", "--server SERVER", "serve using SERVER (thin/puma/webrick/mongrel)") { |s|
50
+ opts.on("-b", "--builder BUILDER_LINE", "evaluate a BUILDER_LINE of code as a builder script") { |line|
51
+ options[:builder] = line
52
+ }
53
+
54
+ opts.on("-s", "--server SERVER", "serve using SERVER (thin/puma/webrick)") { |s|
51
55
  options[:server] = s
52
56
  }
53
57
 
@@ -77,6 +81,24 @@ module Rack
77
81
  options[:pid] = ::File.expand_path(f)
78
82
  }
79
83
 
84
+ opts.separator ""
85
+ opts.separator "Profiling options:"
86
+
87
+ opts.on("--heap HEAPFILE", "Build the application, then dump the heap to HEAPFILE") do |e|
88
+ options[:heapfile] = e
89
+ end
90
+
91
+ opts.on("--profile PROFILE", "Dump CPU or Memory profile to PROFILE (defaults to a tempfile)") do |e|
92
+ options[:profile_file] = e
93
+ end
94
+
95
+ opts.on("--profile-mode MODE", "Profile mode (cpu|wall|object)") do |e|
96
+ { cpu: true, wall: true, object: true }.fetch(e.to_sym) do
97
+ raise OptionParser::InvalidOption, "unknown profile mode: #{e}"
98
+ end
99
+ options[:profile_mode] = e.to_sym
100
+ end
101
+
80
102
  opts.separator ""
81
103
  opts.separator "Common options:"
82
104
 
@@ -114,7 +136,7 @@ module Rack
114
136
 
115
137
  has_options = false
116
138
  server.valid_options.each do |name, description|
117
- next if name.to_s.match(/^(Host|Port)[^a-zA-Z]/) # ignore handler's host and port options, we do our own.
139
+ next if /^(Host|Port)[^a-zA-Z]/.match?(name.to_s) # ignore handler's host and port options, we do our own.
118
140
  info << " -O %-21s %s" % [name, description]
119
141
  has_options = true
120
142
  end
@@ -152,7 +174,9 @@ module Rack
152
174
 
153
175
  # Options may include:
154
176
  # * :app
155
- # a rack application to run (overrides :config)
177
+ # a rack application to run (overrides :config and :builder)
178
+ # * :builder
179
+ # a string to evaluate a Rack::Builder from
156
180
  # * :config
157
181
  # a rackup configuration file path to load (.ru)
158
182
  # * :environment
@@ -182,6 +206,14 @@ module Rack
182
206
  # add given paths to $LOAD_PATH
183
207
  # * :require
184
208
  # require the given libraries
209
+ #
210
+ # Additional options for profiling app initialization include:
211
+ # * :heapfile
212
+ # location for ObjectSpace.dump_all to write the output to
213
+ # * :profile_file
214
+ # location for CPU/Memory (StackProf) profile output (defaults to a tempfile)
215
+ # * :profile_mode
216
+ # StackProf profile mode (cpu|wall|object)
185
217
  def initialize(options = nil)
186
218
  @ignore_options = []
187
219
 
@@ -206,12 +238,12 @@ module Rack
206
238
  default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
207
239
 
208
240
  {
209
- :environment => environment,
210
- :pid => nil,
211
- :Port => 9292,
212
- :Host => default_host,
213
- :AccessLog => [],
214
- :config => "config.ru"
241
+ environment: environment,
242
+ pid: nil,
243
+ Port: 9292,
244
+ Host: default_host,
245
+ AccessLog: [],
246
+ config: "config.ru"
215
247
  }
216
248
  end
217
249
 
@@ -222,21 +254,19 @@ module Rack
222
254
  class << self
223
255
  def logging_middleware
224
256
  lambda { |server|
225
- server.server.name =~ /CGI/ || server.options[:quiet] ? nil : [Rack::CommonLogger, $stderr]
257
+ /CGI/.match?(server.server.name) || server.options[:quiet] ? nil : [Rack::CommonLogger, $stderr]
226
258
  }
227
259
  end
228
260
 
229
261
  def default_middleware_by_environment
230
- m = Hash.new {|h,k| h[k] = []}
262
+ m = Hash.new {|h, k| h[k] = []}
231
263
  m["deployment"] = [
232
264
  [Rack::ContentLength],
233
- [Rack::Chunked],
234
265
  logging_middleware,
235
266
  [Rack::TempfileReaper]
236
267
  ]
237
268
  m["development"] = [
238
269
  [Rack::ContentLength],
239
- [Rack::Chunked],
240
270
  logging_middleware,
241
271
  [Rack::ShowExceptions],
242
272
  [Rack::Lint],
@@ -280,7 +310,9 @@ module Rack
280
310
 
281
311
  # Touch the wrapped app, so that the config.ru is loaded before
282
312
  # daemonization (i.e. before chdir, etc).
283
- wrapped_app
313
+ handle_profiling(options[:heapfile], options[:profile_mode], options[:profile_file]) do
314
+ wrapped_app
315
+ end
284
316
 
285
317
  daemonize_app if options[:daemonize]
286
318
 
@@ -321,6 +353,44 @@ module Rack
321
353
  app
322
354
  end
323
355
 
356
+ def handle_profiling(heapfile, profile_mode, filename)
357
+ if heapfile
358
+ require "objspace"
359
+ ObjectSpace.trace_object_allocations_start
360
+ yield
361
+ GC.start
362
+ ::File.open(heapfile, "w") { |f| ObjectSpace.dump_all(output: f) }
363
+ exit
364
+ end
365
+
366
+ if profile_mode
367
+ require "stackprof"
368
+ require "tempfile"
369
+
370
+ make_profile_name(filename) do |filename|
371
+ ::File.open(filename, "w") do |f|
372
+ StackProf.run(mode: profile_mode, out: f) do
373
+ yield
374
+ end
375
+ puts "Profile written to: #{filename}"
376
+ end
377
+ end
378
+ exit
379
+ end
380
+
381
+ yield
382
+ end
383
+
384
+ def make_profile_name(filename)
385
+ if filename
386
+ yield filename
387
+ else
388
+ ::Dir::Tmpname.create("profile.dump") do |tmpname, _, _|
389
+ yield tmpname
390
+ end
391
+ end
392
+ end
393
+
324
394
  def build_app_from_string
325
395
  Rack::Builder.new_from_string(self.options[:builder])
326
396
  end
@@ -1,3 +1,5 @@
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
 
@@ -42,6 +44,18 @@ module Rack
42
44
  # SessionHash is responsible to lazily load the session from store.
43
45
 
44
46
  class SessionHash
47
+ using Module.new {
48
+ refine Hash do
49
+ def transform_keys(&block)
50
+ hash = {}
51
+ each do |key, value|
52
+ hash[block.call(key)] = value
53
+ end
54
+ hash
55
+ end
56
+ end
57
+ } unless {}.respond_to?(:transform_keys)
58
+
45
59
  include Enumerable
46
60
  attr_writer :id
47
61
 
@@ -84,7 +98,7 @@ module Rack
84
98
  @data[key.to_s]
85
99
  end
86
100
 
87
- def fetch(key, default=Unspecified, &block)
101
+ def fetch(key, default = Unspecified, &block)
88
102
  load_for_read!
89
103
  if default == Unspecified
90
104
  @data.fetch(key.to_s, &block)
@@ -187,11 +201,7 @@ module Rack
187
201
  end
188
202
 
189
203
  def stringify_keys(other)
190
- hash = {}
191
- other.each do |key, value|
192
- hash[key.to_s] = value
193
- end
194
- hash
204
+ other.to_hash.transform_keys(&:to_s)
195
205
  end
196
206
  end
197
207
 
@@ -226,22 +236,22 @@ module Rack
226
236
 
227
237
  class Persisted
228
238
  DEFAULT_OPTIONS = {
229
- :key => RACK_SESSION,
230
- :path => '/',
231
- :domain => nil,
232
- :expire_after => nil,
233
- :secure => false,
234
- :httponly => true,
235
- :defer => false,
236
- :renew => false,
237
- :sidbits => 128,
238
- :cookie_only => true,
239
- :secure_random => ::SecureRandom
239
+ key: RACK_SESSION,
240
+ path: '/',
241
+ domain: nil,
242
+ expire_after: nil,
243
+ secure: false,
244
+ httponly: true,
245
+ defer: false,
246
+ renew: false,
247
+ sidbits: 128,
248
+ cookie_only: true,
249
+ secure_random: ::SecureRandom
240
250
  }.freeze
241
251
 
242
252
  attr_reader :key, :default_options, :sid_secure
243
253
 
244
- def initialize(app, options={})
254
+ def initialize(app, options = {})
245
255
  @app = app
246
256
  @default_options = self.class::DEFAULT_OPTIONS.merge(options)
247
257
  @key = @default_options.delete(:key)
@@ -253,7 +263,7 @@ module Rack
253
263
  context(env)
254
264
  end
255
265
 
256
- def context(env, app=@app)
266
+ def context(env, app = @app)
257
267
  req = make_request env
258
268
  prepare_session(req)
259
269
  status, headers, body = app.call(req.env)
@@ -376,7 +386,7 @@ module Rack
376
386
 
377
387
  session.send(:load!) unless loaded_session?(session)
378
388
  session_id ||= session.id
379
- session_data = session.to_hash.delete_if { |k,v| v.nil? }
389
+ session_data = session.to_hash.delete_if { |k, v| v.nil? }
380
390
 
381
391
  if not data = write_session(req, session_id, session_data, options)
382
392
  req.get_header(RACK_ERRORS).puts("Warning! #{self.class.name} failed to save session. Content dropped.")
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'openssl'
2
4
  require 'zlib'
3
5
  require 'rack/request'
4
6
  require 'rack/response'
5
7
  require 'rack/session/abstract/id'
6
8
  require 'json'
9
+ require 'base64'
7
10
 
8
11
  module Rack
9
12
 
@@ -49,11 +52,11 @@ module Rack
49
52
  # Encode session cookies as Base64
50
53
  class Base64
51
54
  def encode(str)
52
- [str].pack('m')
55
+ ::Base64.strict_encode64(str)
53
56
  end
54
57
 
55
58
  def decode(str)
56
- str.unpack('m').first
59
+ ::Base64.decode64(str)
57
60
  end
58
61
 
59
62
  # Encode session cookies as Marshaled Base64 data
@@ -103,7 +106,7 @@ module Rack
103
106
 
104
107
  attr_reader :coder
105
108
 
106
- def initialize(app, options={})
109
+ def initialize(app, options = {})
107
110
  @secrets = options.values_at(:secret, :old_secret).compact
108
111
  @hmac = options.fetch(:hmac, OpenSSL::Digest::SHA1)
109
112
 
@@ -116,8 +119,8 @@ module Rack
116
119
 
117
120
  Called from: #{caller[0]}.
118
121
  MSG
119
- @coder = options[:coder] ||= Base64::Marshal.new
120
- super(app, options.merge!(:cookie_only => true))
122
+ @coder = options[:coder] ||= Base64::Marshal.new
123
+ super(app, options.merge!(cookie_only: true))
121
124
  end
122
125
 
123
126
  private
@@ -137,9 +140,7 @@ module Rack
137
140
  session_data = request.cookies[@key]
138
141
 
139
142
  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
143
+ session_data, _, digest = session_data.rpartition('--')
143
144
  session_data = nil unless digest_match?(session_data, digest)
144
145
  end
145
146
 
@@ -147,7 +148,7 @@ module Rack
147
148
  end
148
149
  end
149
150
 
150
- def persistent_session_id!(data, sid=nil)
151
+ def persistent_session_id!(data, sid = nil)
151
152
  data ||= {}
152
153
  data["session_id"] ||= sid || generate_sid
153
154
  data
@@ -1,99 +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::PersistedSecure
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.private_id, true)
46
- end
47
- end
48
-
49
- def find_session(req, sid)
50
- with_lock(req) do
51
- unless sid and session = get_session_with_fallback(sid)
52
- sid, session = generate_sid, {}
53
- unless /^STORED/ =~ @pool.add(sid.private_id, session)
54
- raise "Session collision on '#{sid.inspect}'"
55
- end
56
- end
57
- [sid, session]
58
- end
59
- end
60
-
61
- def write_session(req, session_id, new_session, options)
62
- expiry = options[:expire_after]
63
- expiry = expiry.nil? ? 0 : expiry + 1
64
-
65
- with_lock(req) do
66
- @pool.set session_id.private_id, new_session, expiry
67
- session_id
68
- end
69
- end
70
-
71
- def delete_session(req, session_id, options)
72
- with_lock(req) do
73
- @pool.delete(session_id.public_id)
74
- @pool.delete(session_id.private_id)
75
- generate_sid unless options[:drop]
76
- end
77
- end
78
-
79
- def with_lock(req)
80
- @mutex.lock if req.multithread?
81
- yield
82
- rescue MemCache::MemCacheError, Errno::ECONNREFUSED
83
- if $VERBOSE
84
- warn "#{self} is unable to find memcached server."
85
- warn $!.inspect
86
- end
87
- raise
88
- ensure
89
- @mutex.unlock if @mutex.locked?
90
- end
91
-
92
- private
93
-
94
- def get_session_with_fallback(sid)
95
- @pool.get(sid.private_id) || @pool.get(sid.public_id)
96
- end
97
- end
7
+ warn "Rack::Session::Memcache is deprecated, please use Rack::Session::Dalli from 'dalli' gem instead."
8
+ Memcache = Dalli
98
9
  end
99
10
  end
@@ -1,3 +1,5 @@
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
@@ -26,9 +28,9 @@ module Rack
26
28
 
27
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ostruct'
2
4
  require 'erb'
3
5
  require 'rack/request'
@@ -55,7 +57,7 @@ module Rack
55
57
  private :accepts_html?
56
58
 
57
59
  def dump_exception(exception)
58
- string = "#{exception.class}: #{exception.message}\n"
60
+ string = "#{exception.class}: #{exception.message}\n".dup
59
61
  string << exception.backtrace.map { |l| "\t#{l}" }.join("\n")
60
62
  string
61
63
  end
@@ -77,13 +79,13 @@ module Rack
77
79
  frame.function = $4
78
80
 
79
81
  begin
80
- lineno = frame.lineno-1
82
+ lineno = frame.lineno - 1
81
83
  lines = ::File.readlines(frame.filename)
82
- frame.pre_context_lineno = [lineno-CONTEXT, 0].max
84
+ frame.pre_context_lineno = [lineno - CONTEXT, 0].max
83
85
  frame.pre_context = lines[frame.pre_context_lineno...lineno]
84
86
  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]
87
+ frame.post_context_lineno = [lineno + CONTEXT, lines.size].min
88
+ frame.post_context = lines[lineno + 1..frame.post_context_lineno]
87
89
  rescue
88
90
  end
89
91
 
@@ -93,7 +95,11 @@ module Rack
93
95
  end
94
96
  }.compact
95
97
 
96
- TEMPLATE.result(binding)
98
+ template.result(binding)
99
+ end
100
+
101
+ def template
102
+ TEMPLATE
97
103
  end
98
104
 
99
105
  def h(obj) # :nodoc:
@@ -107,8 +113,8 @@ module Rack
107
113
 
108
114
  # :stopdoc:
109
115
 
110
- # adapted from Django <djangoproject.com>
111
- # Copyright (c) 2005, the Lawrence Journal-World
116
+ # adapted from Django <www.djangoproject.com>
117
+ # Copyright (c) Django Software Foundation and individual contributors.
112
118
  # Used under the modified BSD license:
113
119
  # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
114
120
  TEMPLATE = ERB.new(<<-'HTML'.gsub(/^ /, ''))
@@ -363,7 +369,7 @@ module Rack
363
369
  <% env.sort_by { |k, v| k.to_s }.each { |key, val| %>
364
370
  <tr>
365
371
  <td><%=h key %></td>
366
- <td class="code"><div><%=h val %></div></td>
372
+ <td class="code"><div><%=h val.inspect %></div></td>
367
373
  </tr>
368
374
  <% } %>
369
375
  </tbody>
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'erb'
2
4
  require 'rack/request'
3
5
  require 'rack/utils'
@@ -52,8 +54,8 @@ module Rack
52
54
 
53
55
  # :stopdoc:
54
56
 
55
- # adapted from Django <djangoproject.com>
56
- # Copyright (c) 2005, the Lawrence Journal-World
57
+ # adapted from Django <www.djangoproject.com>
58
+ # Copyright (c) Django Software Foundation and individual contributors.
57
59
  # Used under the modified BSD license:
58
60
  # http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
59
61
  TEMPLATE = <<'HTML'