rack 2.0.9.4 → 2.1.0

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 (188) hide show
  1. checksums.yaml +4 -4
  2. data/{HISTORY.md → CHANGELOG.md} +214 -164
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +79 -133
  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 +38 -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 -11
  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 +28 -17
  29. data/lib/rack/directory.rb +17 -14
  30. data/lib/rack/etag.rb +3 -1
  31. data/lib/rack/events.rb +5 -3
  32. data/lib/rack/file.rb +5 -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 +15 -12
  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 +55 -62
  52. data/lib/rack/multipart/uploaded_file.rb +2 -0
  53. data/lib/rack/multipart.rb +6 -3
  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 -16
  64. data/lib/rack/session/abstract/id.rb +40 -22
  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 +64 -93
  74. data/lib/rack.rb +63 -60
  75. data/rack.gemspec +17 -7
  76. metadata +33 -175
  77. data/test/builder/an_underscore_app.rb +0 -5
  78. data/test/builder/anything.rb +0 -5
  79. data/test/builder/comment.ru +0 -4
  80. data/test/builder/end.ru +0 -5
  81. data/test/builder/line.ru +0 -1
  82. data/test/builder/options.ru +0 -2
  83. data/test/cgi/assets/folder/test.js +0 -1
  84. data/test/cgi/assets/fonts/font.eot +0 -1
  85. data/test/cgi/assets/images/image.png +0 -1
  86. data/test/cgi/assets/index.html +0 -1
  87. data/test/cgi/assets/javascripts/app.js +0 -1
  88. data/test/cgi/assets/stylesheets/app.css +0 -1
  89. data/test/cgi/lighttpd.conf +0 -26
  90. data/test/cgi/rackup_stub.rb +0 -6
  91. data/test/cgi/sample_rackup.ru +0 -5
  92. data/test/cgi/test +0 -9
  93. data/test/cgi/test+directory/test+file +0 -1
  94. data/test/cgi/test.fcgi +0 -9
  95. data/test/cgi/test.gz +0 -0
  96. data/test/cgi/test.ru +0 -5
  97. data/test/gemloader.rb +0 -10
  98. data/test/helper.rb +0 -34
  99. data/test/multipart/bad_robots +0 -259
  100. data/test/multipart/binary +0 -0
  101. data/test/multipart/content_type_and_no_filename +0 -6
  102. data/test/multipart/empty +0 -10
  103. data/test/multipart/fail_16384_nofile +0 -814
  104. data/test/multipart/file1.txt +0 -1
  105. data/test/multipart/filename_and_modification_param +0 -7
  106. data/test/multipart/filename_and_no_name +0 -6
  107. data/test/multipart/filename_with_encoded_words +0 -7
  108. data/test/multipart/filename_with_escaped_quotes +0 -6
  109. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  110. data/test/multipart/filename_with_null_byte +0 -7
  111. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  112. data/test/multipart/filename_with_single_quote +0 -7
  113. data/test/multipart/filename_with_unescaped_percentages +0 -6
  114. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  115. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  116. data/test/multipart/filename_with_unescaped_quotes +0 -6
  117. data/test/multipart/ie +0 -6
  118. data/test/multipart/invalid_character +0 -6
  119. data/test/multipart/mixed_files +0 -21
  120. data/test/multipart/nested +0 -10
  121. data/test/multipart/none +0 -9
  122. data/test/multipart/quoted +0 -15
  123. data/test/multipart/rack-logo.png +0 -0
  124. data/test/multipart/semicolon +0 -6
  125. data/test/multipart/text +0 -15
  126. data/test/multipart/three_files_three_fields +0 -31
  127. data/test/multipart/unity3d_wwwform +0 -11
  128. data/test/multipart/webkit +0 -32
  129. data/test/rackup/config.ru +0 -31
  130. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  131. data/test/spec_auth_basic.rb +0 -89
  132. data/test/spec_auth_digest.rb +0 -260
  133. data/test/spec_body_proxy.rb +0 -85
  134. data/test/spec_builder.rb +0 -233
  135. data/test/spec_cascade.rb +0 -63
  136. data/test/spec_cgi.rb +0 -84
  137. data/test/spec_chunked.rb +0 -103
  138. data/test/spec_common_logger.rb +0 -107
  139. data/test/spec_conditional_get.rb +0 -103
  140. data/test/spec_config.rb +0 -23
  141. data/test/spec_content_length.rb +0 -86
  142. data/test/spec_content_type.rb +0 -46
  143. data/test/spec_deflater.rb +0 -375
  144. data/test/spec_directory.rb +0 -148
  145. data/test/spec_etag.rb +0 -108
  146. data/test/spec_events.rb +0 -133
  147. data/test/spec_fastcgi.rb +0 -85
  148. data/test/spec_file.rb +0 -264
  149. data/test/spec_handler.rb +0 -57
  150. data/test/spec_head.rb +0 -46
  151. data/test/spec_lint.rb +0 -520
  152. data/test/spec_lobster.rb +0 -59
  153. data/test/spec_lock.rb +0 -204
  154. data/test/spec_logger.rb +0 -24
  155. data/test/spec_media_type.rb +0 -42
  156. data/test/spec_method_override.rb +0 -110
  157. data/test/spec_mime.rb +0 -51
  158. data/test/spec_mock.rb +0 -359
  159. data/test/spec_multipart.rb +0 -721
  160. data/test/spec_null_logger.rb +0 -21
  161. data/test/spec_recursive.rb +0 -75
  162. data/test/spec_request.rb +0 -1423
  163. data/test/spec_response.rb +0 -528
  164. data/test/spec_rewindable_input.rb +0 -128
  165. data/test/spec_runtime.rb +0 -50
  166. data/test/spec_sendfile.rb +0 -125
  167. data/test/spec_server.rb +0 -193
  168. data/test/spec_session_abstract_id.rb +0 -31
  169. data/test/spec_session_abstract_session_hash.rb +0 -45
  170. data/test/spec_session_cookie.rb +0 -442
  171. data/test/spec_session_memcache.rb +0 -357
  172. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  173. data/test/spec_session_pool.rb +0 -247
  174. data/test/spec_show_exceptions.rb +0 -93
  175. data/test/spec_show_status.rb +0 -104
  176. data/test/spec_static.rb +0 -184
  177. data/test/spec_tempfile_reaper.rb +0 -64
  178. data/test/spec_thin.rb +0 -96
  179. data/test/spec_urlmap.rb +0 -237
  180. data/test/spec_utils.rb +0 -742
  181. data/test/spec_version.rb +0 -11
  182. data/test/spec_webrick.rb +0 -206
  183. data/test/static/another/index.html +0 -1
  184. data/test/static/foo.html +0 -1
  185. data/test/static/index.html +0 -1
  186. data/test/testrequest.rb +0 -78
  187. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  188. 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,12 +254,12 @@ 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
265
  [Rack::Chunked],
@@ -280,7 +312,9 @@ module Rack
280
312
 
281
313
  # Touch the wrapped app, so that the config.ru is loaded before
282
314
  # daemonization (i.e. before chdir, etc).
283
- wrapped_app
315
+ handle_profiling(options[:heapfile], options[:profile_mode], options[:profile_file]) do
316
+ wrapped_app
317
+ end
284
318
 
285
319
  daemonize_app if options[:daemonize]
286
320
 
@@ -321,6 +355,44 @@ module Rack
321
355
  app
322
356
  end
323
357
 
358
+ def handle_profiling(heapfile, profile_mode, filename)
359
+ if heapfile
360
+ require "objspace"
361
+ ObjectSpace.trace_object_allocations_start
362
+ yield
363
+ GC.start
364
+ ::File.open(heapfile, "w") { |f| ObjectSpace.dump_all(output: f) }
365
+ exit
366
+ end
367
+
368
+ if profile_mode
369
+ require "stackprof"
370
+ require "tempfile"
371
+
372
+ make_profile_name(filename) do |filename|
373
+ ::File.open(filename, "w") do |f|
374
+ StackProf.run(mode: profile_mode, out: f) do
375
+ yield
376
+ end
377
+ puts "Profile written to: #{filename}"
378
+ end
379
+ end
380
+ exit
381
+ end
382
+
383
+ yield
384
+ end
385
+
386
+ def make_profile_name(filename)
387
+ if filename
388
+ yield filename
389
+ else
390
+ ::Dir::Tmpname.create("profile.dump") do |tmpname, _, _|
391
+ yield tmpname
392
+ end
393
+ end
394
+ end
395
+
324
396
  def build_app_from_string
325
397
  Rack::Builder.new_from_string(self.options[:builder])
326
398
  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
 
@@ -26,9 +28,9 @@ module Rack
26
28
  end
27
29
 
28
30
  alias :cookie_value :public_id
29
- alias :to_s :public_id
30
31
 
31
32
  def empty?; false; end
33
+ def to_s; raise; end
32
34
  def inspect; public_id.inspect; end
33
35
 
34
36
  private
@@ -42,6 +44,26 @@ 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
+
59
+ def transform_keys(&block)
60
+ hash = dup
61
+ each do |key, value|
62
+ hash[block.call(key)] = value
63
+ end
64
+ hash
65
+ end
66
+
45
67
  include Enumerable
46
68
  attr_writer :id
47
69
 
@@ -84,7 +106,7 @@ module Rack
84
106
  @data[key.to_s]
85
107
  end
86
108
 
87
- def fetch(key, default=Unspecified, &block)
109
+ def fetch(key, default = Unspecified, &block)
88
110
  load_for_read!
89
111
  if default == Unspecified
90
112
  @data.fetch(key.to_s, &block)
@@ -187,11 +209,7 @@ module Rack
187
209
  end
188
210
 
189
211
  def stringify_keys(other)
190
- hash = {}
191
- other.each do |key, value|
192
- hash[key.to_s] = value
193
- end
194
- hash
212
+ other.transform_keys(&:to_s)
195
213
  end
196
214
  end
197
215
 
@@ -226,22 +244,22 @@ module Rack
226
244
 
227
245
  class Persisted
228
246
  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
247
+ key: RACK_SESSION,
248
+ path: '/',
249
+ domain: nil,
250
+ expire_after: nil,
251
+ secure: false,
252
+ httponly: true,
253
+ defer: false,
254
+ renew: false,
255
+ sidbits: 128,
256
+ cookie_only: true,
257
+ secure_random: ::SecureRandom
240
258
  }.freeze
241
259
 
242
260
  attr_reader :key, :default_options, :sid_secure
243
261
 
244
- def initialize(app, options={})
262
+ def initialize(app, options = {})
245
263
  @app = app
246
264
  @default_options = self.class::DEFAULT_OPTIONS.merge(options)
247
265
  @key = @default_options.delete(:key)
@@ -253,7 +271,7 @@ module Rack
253
271
  context(env)
254
272
  end
255
273
 
256
- def context(env, app=@app)
274
+ def context(env, app = @app)
257
275
  req = make_request env
258
276
  prepare_session(req)
259
277
  status, headers, body = app.call(req.env)
@@ -376,7 +394,7 @@ module Rack
376
394
 
377
395
  session.send(:load!) unless loaded_session?(session)
378
396
  session_id ||= session.id
379
- session_data = session.to_hash.delete_if { |k,v| v.nil? }
397
+ session_data = session.to_hash.delete_if { |k, v| v.nil? }
380
398
 
381
399
  if not data = write_session(req, session_id, session_data, options)
382
400
  req.get_header(RACK_ERRORS).puts("Warning! #{self.class.name} failed to save session. Content dropped.")
@@ -442,7 +460,7 @@ module Rack
442
460
  def [](key)
443
461
  if key == "session_id"
444
462
  load_for_read!
445
- id.public_id if id
463
+ id.public_id
446
464
  else
447
465
  super
448
466
  end
@@ -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'