rack 1.6.11 → 2.1.4

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 (187) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +77 -0
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +89 -139
  5. data/Rakefile +27 -28
  6. data/SPEC +6 -7
  7. data/bin/rackup +1 -0
  8. data/contrib/rack_logo.svg +164 -111
  9. data/example/lobster.ru +2 -0
  10. data/example/protectedlobster.rb +4 -2
  11. data/example/protectedlobster.ru +3 -1
  12. data/lib/rack/auth/abstract/handler.rb +3 -1
  13. data/lib/rack/auth/abstract/request.rb +7 -1
  14. data/lib/rack/auth/basic.rb +4 -1
  15. data/lib/rack/auth/digest/md5.rb +9 -7
  16. data/lib/rack/auth/digest/nonce.rb +6 -3
  17. data/lib/rack/auth/digest/params.rb +5 -4
  18. data/lib/rack/auth/digest/request.rb +3 -1
  19. data/lib/rack/body_proxy.rb +11 -9
  20. data/lib/rack/builder.rb +42 -18
  21. data/lib/rack/cascade.rb +6 -5
  22. data/lib/rack/chunked.rb +33 -10
  23. data/lib/rack/{commonlogger.rb → common_logger.rb} +11 -10
  24. data/lib/rack/{conditionalget.rb → conditional_get.rb} +3 -1
  25. data/lib/rack/config.rb +2 -0
  26. data/lib/rack/content_length.rb +5 -3
  27. data/lib/rack/content_type.rb +3 -1
  28. data/lib/rack/core_ext/regexp.rb +14 -0
  29. data/lib/rack/deflater.rb +33 -53
  30. data/lib/rack/directory.rb +75 -60
  31. data/lib/rack/etag.rb +8 -5
  32. data/lib/rack/events.rb +156 -0
  33. data/lib/rack/file.rb +4 -149
  34. data/lib/rack/files.rb +178 -0
  35. data/lib/rack/handler/cgi.rb +18 -17
  36. data/lib/rack/handler/fastcgi.rb +17 -16
  37. data/lib/rack/handler/lsws.rb +14 -12
  38. data/lib/rack/handler/scgi.rb +22 -19
  39. data/lib/rack/handler/thin.rb +6 -1
  40. data/lib/rack/handler/webrick.rb +28 -28
  41. data/lib/rack/handler.rb +9 -26
  42. data/lib/rack/head.rb +17 -17
  43. data/lib/rack/lint.rb +54 -51
  44. data/lib/rack/lobster.rb +8 -6
  45. data/lib/rack/lock.rb +17 -10
  46. data/lib/rack/logger.rb +4 -2
  47. data/lib/rack/media_type.rb +43 -0
  48. data/lib/rack/{methodoverride.rb → method_override.rb} +10 -8
  49. data/lib/rack/mime.rb +27 -6
  50. data/lib/rack/mock.rb +101 -60
  51. data/lib/rack/multipart/generator.rb +11 -12
  52. data/lib/rack/multipart/parser.rb +280 -161
  53. data/lib/rack/multipart/uploaded_file.rb +3 -2
  54. data/lib/rack/multipart.rb +39 -8
  55. data/lib/rack/{nulllogger.rb → null_logger.rb} +3 -1
  56. data/lib/rack/query_parser.rb +218 -0
  57. data/lib/rack/recursive.rb +11 -9
  58. data/lib/rack/reloader.rb +10 -4
  59. data/lib/rack/request.rb +447 -305
  60. data/lib/rack/response.rb +196 -83
  61. data/lib/rack/rewindable_input.rb +5 -14
  62. data/lib/rack/runtime.rb +12 -18
  63. data/lib/rack/sendfile.rb +19 -14
  64. data/lib/rack/server.rb +118 -41
  65. data/lib/rack/session/abstract/id.rb +215 -94
  66. data/lib/rack/session/cookie.rb +45 -28
  67. data/lib/rack/session/memcache.rb +4 -87
  68. data/lib/rack/session/pool.rb +25 -16
  69. data/lib/rack/show_exceptions.rb +392 -0
  70. data/lib/rack/{showstatus.rb → show_status.rb} +7 -5
  71. data/lib/rack/static.rb +41 -11
  72. data/lib/rack/tempfile_reaper.rb +4 -2
  73. data/lib/rack/urlmap.rb +25 -15
  74. data/lib/rack/utils.rb +186 -272
  75. data/lib/rack.rb +76 -24
  76. data/rack.gemspec +25 -14
  77. metadata +62 -182
  78. data/HISTORY.md +0 -375
  79. data/KNOWN-ISSUES +0 -44
  80. data/lib/rack/backports/uri/common_18.rb +0 -56
  81. data/lib/rack/backports/uri/common_192.rb +0 -52
  82. data/lib/rack/backports/uri/common_193.rb +0 -29
  83. data/lib/rack/handler/evented_mongrel.rb +0 -8
  84. data/lib/rack/handler/mongrel.rb +0 -106
  85. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  86. data/lib/rack/showexceptions.rb +0 -387
  87. data/lib/rack/utils/okjson.rb +0 -600
  88. data/test/builder/anything.rb +0 -5
  89. data/test/builder/comment.ru +0 -4
  90. data/test/builder/end.ru +0 -5
  91. data/test/builder/line.ru +0 -1
  92. data/test/builder/options.ru +0 -2
  93. data/test/cgi/assets/folder/test.js +0 -1
  94. data/test/cgi/assets/fonts/font.eot +0 -1
  95. data/test/cgi/assets/images/image.png +0 -1
  96. data/test/cgi/assets/index.html +0 -1
  97. data/test/cgi/assets/javascripts/app.js +0 -1
  98. data/test/cgi/assets/stylesheets/app.css +0 -1
  99. data/test/cgi/lighttpd.conf +0 -26
  100. data/test/cgi/rackup_stub.rb +0 -6
  101. data/test/cgi/sample_rackup.ru +0 -5
  102. data/test/cgi/test +0 -9
  103. data/test/cgi/test+directory/test+file +0 -1
  104. data/test/cgi/test.fcgi +0 -8
  105. data/test/cgi/test.ru +0 -5
  106. data/test/gemloader.rb +0 -10
  107. data/test/multipart/bad_robots +0 -259
  108. data/test/multipart/binary +0 -0
  109. data/test/multipart/content_type_and_no_filename +0 -6
  110. data/test/multipart/empty +0 -10
  111. data/test/multipart/fail_16384_nofile +0 -814
  112. data/test/multipart/file1.txt +0 -1
  113. data/test/multipart/filename_and_modification_param +0 -7
  114. data/test/multipart/filename_and_no_name +0 -6
  115. data/test/multipart/filename_with_escaped_quotes +0 -6
  116. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  117. data/test/multipart/filename_with_null_byte +0 -7
  118. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  119. data/test/multipart/filename_with_unescaped_percentages +0 -6
  120. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  121. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  122. data/test/multipart/filename_with_unescaped_quotes +0 -6
  123. data/test/multipart/ie +0 -6
  124. data/test/multipart/invalid_character +0 -6
  125. data/test/multipart/mixed_files +0 -21
  126. data/test/multipart/nested +0 -10
  127. data/test/multipart/none +0 -9
  128. data/test/multipart/semicolon +0 -6
  129. data/test/multipart/text +0 -15
  130. data/test/multipart/three_files_three_fields +0 -31
  131. data/test/multipart/webkit +0 -32
  132. data/test/rackup/config.ru +0 -31
  133. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  134. data/test/spec_auth_basic.rb +0 -81
  135. data/test/spec_auth_digest.rb +0 -259
  136. data/test/spec_body_proxy.rb +0 -85
  137. data/test/spec_builder.rb +0 -223
  138. data/test/spec_cascade.rb +0 -61
  139. data/test/spec_cgi.rb +0 -102
  140. data/test/spec_chunked.rb +0 -101
  141. data/test/spec_commonlogger.rb +0 -93
  142. data/test/spec_conditionalget.rb +0 -102
  143. data/test/spec_config.rb +0 -22
  144. data/test/spec_content_length.rb +0 -85
  145. data/test/spec_content_type.rb +0 -45
  146. data/test/spec_deflater.rb +0 -339
  147. data/test/spec_directory.rb +0 -88
  148. data/test/spec_etag.rb +0 -107
  149. data/test/spec_fastcgi.rb +0 -107
  150. data/test/spec_file.rb +0 -221
  151. data/test/spec_handler.rb +0 -72
  152. data/test/spec_head.rb +0 -45
  153. data/test/spec_lint.rb +0 -550
  154. data/test/spec_lobster.rb +0 -58
  155. data/test/spec_lock.rb +0 -164
  156. data/test/spec_logger.rb +0 -23
  157. data/test/spec_methodoverride.rb +0 -111
  158. data/test/spec_mime.rb +0 -51
  159. data/test/spec_mock.rb +0 -297
  160. data/test/spec_mongrel.rb +0 -182
  161. data/test/spec_multipart.rb +0 -600
  162. data/test/spec_nulllogger.rb +0 -20
  163. data/test/spec_recursive.rb +0 -72
  164. data/test/spec_request.rb +0 -1232
  165. data/test/spec_response.rb +0 -407
  166. data/test/spec_rewindable_input.rb +0 -118
  167. data/test/spec_runtime.rb +0 -49
  168. data/test/spec_sendfile.rb +0 -130
  169. data/test/spec_server.rb +0 -167
  170. data/test/spec_session_abstract_id.rb +0 -53
  171. data/test/spec_session_cookie.rb +0 -410
  172. data/test/spec_session_memcache.rb +0 -321
  173. data/test/spec_session_pool.rb +0 -209
  174. data/test/spec_showexceptions.rb +0 -98
  175. data/test/spec_showstatus.rb +0 -103
  176. data/test/spec_static.rb +0 -145
  177. data/test/spec_tempfile_reaper.rb +0 -63
  178. data/test/spec_thin.rb +0 -91
  179. data/test/spec_urlmap.rb +0 -236
  180. data/test/spec_utils.rb +0 -647
  181. data/test/spec_version.rb +0 -17
  182. data/test/spec_webrick.rb +0 -184
  183. data/test/static/another/index.html +0 -1
  184. data/test/static/index.html +0 -1
  185. data/test/testrequest.rb +0 -78
  186. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  187. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/lib/rack/lint.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack/utils'
2
4
  require 'forwardable'
3
5
 
@@ -15,8 +17,8 @@ module Rack
15
17
 
16
18
  class LintError < RuntimeError; end
17
19
  module Assertion
18
- def assert(message, &block)
19
- unless block.call
20
+ def assert(message)
21
+ unless yield
20
22
  raise LintError, message
21
23
  end
22
24
  end
@@ -33,7 +35,7 @@ module Rack
33
35
 
34
36
  ## A Rack application is a Ruby object (not a class) that
35
37
  ## responds to +call+.
36
- def call(env=nil)
38
+ def call(env = nil)
37
39
  dup._call(env)
38
40
  end
39
41
 
@@ -42,8 +44,8 @@ module Rack
42
44
  assert("No env given") { env }
43
45
  check_env env
44
46
 
45
- env['rack.input'] = InputWrapper.new(env['rack.input'])
46
- env['rack.errors'] = ErrorWrapper.new(env['rack.errors'])
47
+ env[RACK_INPUT] = InputWrapper.new(env[RACK_INPUT])
48
+ env[RACK_ERRORS] = ErrorWrapper.new(env[RACK_ERRORS])
47
49
 
48
50
  ## and returns an Array of exactly three values:
49
51
  status, headers, @body = @app.call(env)
@@ -57,7 +59,7 @@ module Rack
57
59
  ## and the *body*.
58
60
  check_content_type status, headers
59
61
  check_content_length status, headers
60
- @head_request = env[REQUEST_METHOD] == "HEAD"
62
+ @head_request = env[REQUEST_METHOD] == HEAD
61
63
  [status, headers, self]
62
64
  end
63
65
 
@@ -95,7 +97,7 @@ module Rack
95
97
  ## empty string, if the request URL targets
96
98
  ## the application root and does not have a
97
99
  ## trailing slash. This value may be
98
- ## percent-encoded when I originating from
100
+ ## percent-encoded when originating from
99
101
  ## a URL.
100
102
 
101
103
  ## <tt>QUERY_STRING</tt>:: The portion of the request URL that
@@ -123,9 +125,8 @@ module Rack
123
125
  ## the presence or absence of the
124
126
  ## appropriate HTTP header in the
125
127
  ## request. See
126
- ## <a href="https://tools.ietf.org/html/rfc3875#section-4.1.18">
127
- ## RFC3875 section 4.1.18</a> for
128
- ## specific behavior.
128
+ ## {RFC3875 section 4.1.18}[https://tools.ietf.org/html/rfc3875#section-4.1.18]
129
+ ## for specific behavior.
129
130
 
130
131
  ## In addition to this, the Rack environment must include these
131
132
  ## Rack-specific variables:
@@ -177,7 +178,7 @@ module Rack
177
178
  ## <tt>rack.session</tt>:: A hash like interface for storing
178
179
  ## request session data.
179
180
  ## The store must implement:
180
- if session = env['rack.session']
181
+ if session = env[RACK_SESSION]
181
182
  ## store(key, value) (aliased as []=);
182
183
  assert("session #{session.inspect} must respond to store and []=") {
183
184
  session.respond_to?(:store) && session.respond_to?(:[]=)
@@ -201,7 +202,7 @@ module Rack
201
202
 
202
203
  ## <tt>rack.logger</tt>:: A common object interface for logging messages.
203
204
  ## The object must implement:
204
- if logger = env['rack.logger']
205
+ if logger = env[RACK_LOGGER]
205
206
  ## info(message, &block)
206
207
  assert("logger #{logger.inspect} must respond to info") {
207
208
  logger.respond_to?(:info)
@@ -229,16 +230,16 @@ module Rack
229
230
  end
230
231
 
231
232
  ## <tt>rack.multipart.buffer_size</tt>:: An Integer hint to the multipart parser as to what chunk size to use for reads and writes.
232
- if bufsize = env['rack.multipart.buffer_size']
233
+ if bufsize = env[RACK_MULTIPART_BUFFER_SIZE]
233
234
  assert("rack.multipart.buffer_size must be an Integer > 0 if specified") {
234
235
  bufsize.is_a?(Integer) && bufsize > 0
235
236
  }
236
237
  end
237
238
 
238
239
  ## <tt>rack.multipart.tempfile_factory</tt>:: An object responding to #call with two arguments, the filename and content_type given for the multipart form field, and returning an IO-like object that responds to #<< and optionally #rewind. This factory will be used to instantiate the tempfile for each multipart form file upload field, rather than the default class of Tempfile.
239
- if tempfile_factory = env['rack.multipart.tempfile_factory']
240
+ if tempfile_factory = env[RACK_MULTIPART_TEMPFILE_FACTORY]
240
241
  assert("rack.multipart.tempfile_factory must respond to #call") { tempfile_factory.respond_to?(:call) }
241
- env['rack.multipart.tempfile_factory'] = lambda do |filename, content_type|
242
+ env[RACK_MULTIPART_TEMPFILE_FACTORY] = lambda do |filename, content_type|
242
243
  io = tempfile_factory.call(filename, content_type)
243
244
  assert("rack.multipart.tempfile_factory return value must respond to #<<") { io.respond_to?(:<<) }
244
245
  io
@@ -263,7 +264,7 @@ module Rack
263
264
  ## <tt>HTTP_CONTENT_TYPE</tt> or <tt>HTTP_CONTENT_LENGTH</tt>
264
265
  ## (use the versions without <tt>HTTP_</tt>).
265
266
  %w[HTTP_CONTENT_TYPE HTTP_CONTENT_LENGTH].each { |header|
266
- assert("env contains #{header}, must use #{header[5,-1]}") {
267
+ assert("env contains #{header}, must use #{header[5, -1]}") {
267
268
  not env.include? header
268
269
  }
269
270
  }
@@ -279,37 +280,37 @@ module Rack
279
280
  ## There are the following restrictions:
280
281
 
281
282
  ## * <tt>rack.version</tt> must be an array of Integers.
282
- assert("rack.version must be an Array, was #{env["rack.version"].class}") {
283
- env["rack.version"].kind_of? Array
283
+ assert("rack.version must be an Array, was #{env[RACK_VERSION].class}") {
284
+ env[RACK_VERSION].kind_of? Array
284
285
  }
285
286
  ## * <tt>rack.url_scheme</tt> must either be +http+ or +https+.
286
- assert("rack.url_scheme unknown: #{env["rack.url_scheme"].inspect}") {
287
- %w[http https].include? env["rack.url_scheme"]
287
+ assert("rack.url_scheme unknown: #{env[RACK_URL_SCHEME].inspect}") {
288
+ %w[http https].include?(env[RACK_URL_SCHEME])
288
289
  }
289
290
 
290
291
  ## * There must be a valid input stream in <tt>rack.input</tt>.
291
- check_input env["rack.input"]
292
+ check_input env[RACK_INPUT]
292
293
  ## * There must be a valid error stream in <tt>rack.errors</tt>.
293
- check_error env["rack.errors"]
294
+ check_error env[RACK_ERRORS]
294
295
  ## * There may be a valid hijack stream in <tt>rack.hijack_io</tt>
295
296
  check_hijack env
296
297
 
297
298
  ## * The <tt>REQUEST_METHOD</tt> must be a valid token.
298
299
  assert("REQUEST_METHOD unknown: #{env[REQUEST_METHOD]}") {
299
- env["REQUEST_METHOD"] =~ /\A[0-9A-Za-z!\#$%&'*+.^_`|~-]+\z/
300
+ env[REQUEST_METHOD] =~ /\A[0-9A-Za-z!\#$%&'*+.^_`|~-]+\z/
300
301
  }
301
302
 
302
303
  ## * The <tt>SCRIPT_NAME</tt>, if non-empty, must start with <tt>/</tt>
303
304
  assert("SCRIPT_NAME must start with /") {
304
- !env.include?("SCRIPT_NAME") ||
305
- env["SCRIPT_NAME"] == "" ||
306
- env["SCRIPT_NAME"] =~ /\A\//
305
+ !env.include?(SCRIPT_NAME) ||
306
+ env[SCRIPT_NAME] == "" ||
307
+ env[SCRIPT_NAME] =~ /\A\//
307
308
  }
308
309
  ## * The <tt>PATH_INFO</tt>, if non-empty, must start with <tt>/</tt>
309
310
  assert("PATH_INFO must start with /") {
310
- !env.include?("PATH_INFO") ||
311
- env["PATH_INFO"] == "" ||
312
- env["PATH_INFO"] =~ /\A\//
311
+ !env.include?(PATH_INFO) ||
312
+ env[PATH_INFO] == "" ||
313
+ env[PATH_INFO] =~ /\A\//
313
314
  }
314
315
  ## * The <tt>CONTENT_LENGTH</tt>, if given, must consist of digits only.
315
316
  assert("Invalid CONTENT_LENGTH: #{env["CONTENT_LENGTH"]}") {
@@ -320,11 +321,11 @@ module Rack
320
321
  ## set. <tt>PATH_INFO</tt> should be <tt>/</tt> if
321
322
  ## <tt>SCRIPT_NAME</tt> is empty.
322
323
  assert("One of SCRIPT_NAME or PATH_INFO must be set (make PATH_INFO '/' if SCRIPT_NAME is empty)") {
323
- env["SCRIPT_NAME"] || env["PATH_INFO"]
324
+ env[SCRIPT_NAME] || env[PATH_INFO]
324
325
  }
325
326
  ## <tt>SCRIPT_NAME</tt> never should be <tt>/</tt>, but instead be empty.
326
327
  assert("SCRIPT_NAME cannot be '/', make it '' and PATH_INFO '/'") {
327
- env["SCRIPT_NAME"] != "/"
328
+ env[SCRIPT_NAME] != "/"
328
329
  }
329
330
  end
330
331
 
@@ -518,11 +519,11 @@ module Rack
518
519
  #
519
520
  ## ==== Request (before status)
520
521
  def check_hijack(env)
521
- if env['rack.hijack?']
522
+ if env[RACK_IS_HIJACK]
522
523
  ## If rack.hijack? is true then rack.hijack must respond to #call.
523
- original_hijack = env['rack.hijack']
524
+ original_hijack = env[RACK_HIJACK]
524
525
  assert("rack.hijack must respond to call") { original_hijack.respond_to?(:call) }
525
- env['rack.hijack'] = proc do
526
+ env[RACK_HIJACK] = proc do
526
527
  ## rack.hijack must return the io that will also be assigned (or is
527
528
  ## already present, in rack.hijack_io.
528
529
  io = original_hijack.call
@@ -548,16 +549,16 @@ module Rack
548
549
  ## hijack_io to provide additional features to users. The purpose of
549
550
  ## rack.hijack is for Rack to "get out of the way", as such, Rack only
550
551
  ## provides the minimum of specification and support.
551
- env['rack.hijack_io'] = HijackWrapper.new(env['rack.hijack_io'])
552
+ env[RACK_HIJACK_IO] = HijackWrapper.new(env[RACK_HIJACK_IO])
552
553
  io
553
554
  end
554
555
  else
555
556
  ##
556
557
  ## If rack.hijack? is false, then rack.hijack should not be set.
557
- assert("rack.hijack? is false, but rack.hijack is present") { env['rack.hijack'].nil? }
558
+ assert("rack.hijack? is false, but rack.hijack is present") { env[RACK_HIJACK].nil? }
558
559
  ##
559
560
  ## If rack.hijack? is false, then rack.hijack_io should not be set.
560
- assert("rack.hijack? is false, but rack.hijack_io is present") { env['rack.hijack_io'].nil? }
561
+ assert("rack.hijack? is false, but rack.hijack_io is present") { env[RACK_HIJACK_IO].nil? }
561
562
  end
562
563
  end
563
564
 
@@ -587,12 +588,12 @@ module Rack
587
588
  ## Servers must ignore the <tt>body</tt> part of the response tuple when
588
589
  ## the <tt>rack.hijack</tt> response API is in use.
589
590
 
590
- if env['rack.hijack?'] && headers['rack.hijack']
591
+ if env[RACK_IS_HIJACK] && headers[RACK_HIJACK]
591
592
  assert('rack.hijack header must respond to #call') {
592
- headers['rack.hijack'].respond_to? :call
593
+ headers[RACK_HIJACK].respond_to? :call
593
594
  }
594
- original_hijack = headers['rack.hijack']
595
- headers['rack.hijack'] = proc do |io|
595
+ original_hijack = headers[RACK_HIJACK]
596
+ headers[RACK_HIJACK] = proc do |io|
596
597
  original_hijack.call HijackWrapper.new(io)
597
598
  end
598
599
  else
@@ -600,7 +601,7 @@ module Rack
600
601
  ## The special response header <tt>rack.hijack</tt> must only be set
601
602
  ## if the request env has <tt>rack.hijack?</tt> <tt>true</tt>.
602
603
  assert('rack.hijack header must not be present if server does not support hijacking') {
603
- headers['rack.hijack'].nil?
604
+ headers[RACK_HIJACK].nil?
604
605
  }
605
606
  end
606
607
  end
@@ -626,15 +627,17 @@ module Rack
626
627
  assert("headers object should respond to #each, but doesn't (got #{header.class} as headers)") {
627
628
  header.respond_to? :each
628
629
  }
629
- header.each { |key, value|
630
- ## Special headers starting "rack." are for communicating with the
631
- ## server, and must not be sent back to the client.
632
- next if key =~ /^rack\..+$/
633
630
 
631
+ header.each { |key, value|
634
632
  ## The header keys must be Strings.
635
633
  assert("header key must be a string, was #{key.class}") {
636
634
  key.kind_of? String
637
635
  }
636
+
637
+ ## Special headers starting "rack." are for communicating with the
638
+ ## server, and must not be sent back to the client.
639
+ next if key =~ /^rack\..+$/
640
+
638
641
  ## The header must not contain a +Status+ key.
639
642
  assert("header must not contain Status") { key.downcase != "status" }
640
643
  ## The header must conform to RFC7230 token specification, i.e. cannot
@@ -659,10 +662,10 @@ module Rack
659
662
  def check_content_type(status, headers)
660
663
  headers.each { |key, value|
661
664
  ## There must not be a <tt>Content-Type</tt>, when the +Status+ is 1xx,
662
- ## 204, 205 or 304.
665
+ ## 204 or 304.
663
666
  if key.downcase == "content-type"
664
667
  assert("Content-Type header found in #{status} response, not allowed") {
665
- not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
668
+ not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.key? status.to_i
666
669
  }
667
670
  return
668
671
  end
@@ -674,9 +677,9 @@ module Rack
674
677
  headers.each { |key, value|
675
678
  if key.downcase == 'content-length'
676
679
  ## There must not be a <tt>Content-Length</tt> header when the
677
- ## +Status+ is 1xx, 204, 205 or 304.
680
+ ## +Status+ is 1xx, 204 or 304.
678
681
  assert("Content-Length header found in #{status} response, not allowed") {
679
- not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include? status.to_i
682
+ not Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.key? status.to_i
680
683
  }
681
684
  @content_length = value
682
685
  end
@@ -710,7 +713,7 @@ module Rack
710
713
  assert("Body yielded non-string value #{part.inspect}") {
711
714
  part.kind_of? String
712
715
  }
713
- bytes += Rack::Utils.bytesize(part)
716
+ bytes += part.bytesize
714
717
  yield part
715
718
  }
716
719
  verify_content_length(bytes)
data/lib/rack/lobster.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'zlib'
2
4
 
3
5
  require 'rack/request'
@@ -25,8 +27,8 @@ module Rack
25
27
  content = ["<title>Lobstericious!</title>",
26
28
  "<pre>", lobster, "</pre>",
27
29
  "<a href='#{href}'>flip!</a>"]
28
- length = content.inject(0) { |a,e| a+e.size }.to_s
29
- [200, {CONTENT_TYPE => "text/html", CONTENT_LENGTH => length}, content]
30
+ length = content.inject(0) { |a, e| a + e.size }.to_s
31
+ [200, { CONTENT_TYPE => "text/html", CONTENT_LENGTH => length }, content]
30
32
  }
31
33
 
32
34
  def call(env)
@@ -37,8 +39,8 @@ module Rack
37
39
  gsub('\\', 'TEMP').
38
40
  gsub('/', '\\').
39
41
  gsub('TEMP', '/').
40
- gsub('{','}').
41
- gsub('(',')')
42
+ gsub('{', '}').
43
+ gsub('(', ')')
42
44
  end.join("\n")
43
45
  href = "?flip=right"
44
46
  elsif req.GET["flip"] == "crash"
@@ -63,8 +65,8 @@ end
63
65
 
64
66
  if $0 == __FILE__
65
67
  require 'rack'
66
- require 'rack/showexceptions'
68
+ require 'rack/show_exceptions'
67
69
  Rack::Server.start(
68
- :app => Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), :Port => 9292
70
+ app: Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), Port: 9292
69
71
  )
70
72
  end
data/lib/rack/lock.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thread'
2
4
  require 'rack/body_proxy'
3
5
 
@@ -5,22 +7,27 @@ module Rack
5
7
  # Rack::Lock locks every request inside a mutex, so that every request
6
8
  # will effectively be executed synchronously.
7
9
  class Lock
8
- FLAG = 'rack.multithread'.freeze
9
-
10
10
  def initialize(app, mutex = Mutex.new)
11
11
  @app, @mutex = app, mutex
12
12
  end
13
13
 
14
14
  def call(env)
15
- old, env[FLAG] = env[FLAG], false
16
15
  @mutex.lock
17
- response = @app.call(env)
18
- body = BodyProxy.new(response[2]) { @mutex.unlock }
19
- response[2] = body
20
- response
21
- ensure
22
- @mutex.unlock unless body
23
- env[FLAG] = old
16
+ @env = env
17
+ @old_rack_multithread = env[RACK_MULTITHREAD]
18
+ begin
19
+ response = @app.call(env.merge!(RACK_MULTITHREAD => false))
20
+ returned = response << BodyProxy.new(response.pop) { unlock }
21
+ ensure
22
+ unlock unless returned
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def unlock
29
+ @mutex.unlock
30
+ @env[RACK_MULTITHREAD] = @old_rack_multithread
24
31
  end
25
32
  end
26
33
  end
data/lib/rack/logger.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'logger'
2
4
 
3
5
  module Rack
@@ -8,10 +10,10 @@ module Rack
8
10
  end
9
11
 
10
12
  def call(env)
11
- logger = ::Logger.new(env['rack.errors'])
13
+ logger = ::Logger.new(env[RACK_ERRORS])
12
14
  logger.level = @level
13
15
 
14
- env['rack.logger'] = logger
16
+ env[RACK_LOGGER] = logger
15
17
  @app.call(env)
16
18
  end
17
19
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ # Rack::MediaType parse media type and parameters out of content_type string
5
+
6
+ class MediaType
7
+ SPLIT_PATTERN = %r{\s*[;,]\s*}
8
+
9
+ class << self
10
+ # The media type (type/subtype) portion of the CONTENT_TYPE header
11
+ # without any media type parameters. e.g., when CONTENT_TYPE is
12
+ # "text/plain;charset=utf-8", the media-type is "text/plain".
13
+ #
14
+ # For more information on the use of media types in HTTP, see:
15
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
16
+ def type(content_type)
17
+ return nil unless content_type
18
+ content_type.split(SPLIT_PATTERN, 2).first.tap &:downcase!
19
+ end
20
+
21
+ # The media type parameters provided in CONTENT_TYPE as a Hash, or
22
+ # an empty Hash if no CONTENT_TYPE or media-type parameters were
23
+ # provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8",
24
+ # this method responds with the following Hash:
25
+ # { 'charset' => 'utf-8' }
26
+ def params(content_type)
27
+ return {} if content_type.nil?
28
+
29
+ content_type.split(SPLIT_PATTERN)[1..-1].each_with_object({}) do |s, hsh|
30
+ k, v = s.split('=', 2)
31
+
32
+ hsh[k.tap(&:downcase!)] = strip_doublequotes(v)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def strip_doublequotes(str)
39
+ (str.start_with?('"') && str.end_with?('"')) ? str[1..-2] : str
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  class MethodOverride
3
- HTTP_METHODS = %w(GET HEAD PUT POST DELETE OPTIONS PATCH LINK UNLINK)
5
+ HTTP_METHODS = %w[GET HEAD PUT POST DELETE OPTIONS PATCH LINK UNLINK]
4
6
 
5
- METHOD_OVERRIDE_PARAM_KEY = "_method".freeze
6
- HTTP_METHOD_OVERRIDE_HEADER = "HTTP_X_HTTP_METHOD_OVERRIDE".freeze
7
- ALLOWED_METHODS = ["POST"]
7
+ METHOD_OVERRIDE_PARAM_KEY = "_method"
8
+ HTTP_METHOD_OVERRIDE_HEADER = "HTTP_X_HTTP_METHOD_OVERRIDE"
9
+ ALLOWED_METHODS = %w[POST]
8
10
 
9
11
  def initialize(app)
10
12
  @app = app
@@ -14,7 +16,7 @@ module Rack
14
16
  if allowed_methods.include?(env[REQUEST_METHOD])
15
17
  method = method_override(env)
16
18
  if HTTP_METHODS.include?(method)
17
- env["rack.methodoverride.original_method"] = env[REQUEST_METHOD]
19
+ env[RACK_METHODOVERRIDE_ORIGINAL_METHOD] = env[REQUEST_METHOD]
18
20
  env[REQUEST_METHOD] = method
19
21
  end
20
22
  end
@@ -29,7 +31,7 @@ module Rack
29
31
  begin
30
32
  method.to_s.upcase
31
33
  rescue ArgumentError
32
- env["rack.errors"].puts "Invalid string for method"
34
+ env[RACK_ERRORS].puts "Invalid string for method"
33
35
  end
34
36
  end
35
37
 
@@ -42,9 +44,9 @@ module Rack
42
44
  def method_override_param(req)
43
45
  req.POST[METHOD_OVERRIDE_PARAM_KEY]
44
46
  rescue Utils::InvalidParameterError, Utils::ParameterTypeError
45
- req.env["rack.errors"].puts "Invalid or incomplete POST params"
47
+ req.get_header(RACK_ERRORS).puts "Invalid or incomplete POST params"
46
48
  rescue EOFError
47
- req.env["rack.errors"].puts "Bad request content body"
49
+ req.get_header(RACK_ERRORS).puts "Bad request content body"
48
50
  end
49
51
  end
50
52
  end
data/lib/rack/mime.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  module Mime
3
5
  # Returns String with mime type if found, otherwise use +fallback+.
@@ -13,7 +15,7 @@ module Rack
13
15
  # This is a shortcut for:
14
16
  # Rack::Mime::MIME_TYPES.fetch('.foo', 'application/octet-stream')
15
17
 
16
- def mime_type(ext, fallback='application/octet-stream')
18
+ def mime_type(ext, fallback = 'application/octet-stream')
17
19
  MIME_TYPES.fetch(ext.to_s.downcase, fallback)
18
20
  end
19
21
  module_function :mime_type
@@ -45,11 +47,6 @@ module Rack
45
47
  #
46
48
  # N.B. On Ubuntu the mime.types file does not include the leading period, so
47
49
  # users may need to modify the data before merging into the hash.
48
- #
49
- # To add the list mongrel provides, use:
50
- #
51
- # require 'mongrel/handlers'
52
- # Rack::Mime::MIME_TYPES.merge!(Mongrel::DirHandler::MIME_TYPES)
53
50
 
54
51
  MIME_TYPES = {
55
52
  ".123" => "application/vnd.lotus-1-2-3",
@@ -154,8 +151,11 @@ module Rack
154
151
  ".dmg" => "application/octet-stream",
155
152
  ".dna" => "application/vnd.dna",
156
153
  ".doc" => "application/msword",
154
+ ".docm" => "application/vnd.ms-word.document.macroEnabled.12",
157
155
  ".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
158
156
  ".dot" => "application/msword",
157
+ ".dotm" => "application/vnd.ms-word.template.macroEnabled.12",
158
+ ".dotx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
159
159
  ".dp" => "application/vnd.osgi.dp",
160
160
  ".dpg" => "application/vnd.dpgraph",
161
161
  ".dsc" => "text/prs.lines.tag",
@@ -308,6 +308,7 @@ module Rack
308
308
  ".lvp" => "audio/vnd.lucent.voice",
309
309
  ".lwp" => "application/vnd.lotus-wordpro",
310
310
  ".m3u" => "audio/x-mpegurl",
311
+ ".m3u8" => "application/x-mpegurl",
311
312
  ".m4a" => "audio/mp4a-latm",
312
313
  ".m4v" => "video/mp4",
313
314
  ".ma" => "application/mathematica",
@@ -345,6 +346,7 @@ module Rack
345
346
  ".mp4s" => "application/mp4",
346
347
  ".mp4v" => "video/mp4",
347
348
  ".mpc" => "application/vnd.mophun.certificate",
349
+ ".mpd" => "application/dash+xml",
348
350
  ".mpeg" => "video/mpeg",
349
351
  ".mpg" => "video/mpeg",
350
352
  ".mpga" => "audio/mpeg",
@@ -444,10 +446,19 @@ module Rack
444
446
  ".pnm" => "image/x-portable-anymap",
445
447
  ".pntg" => "image/x-macpaint",
446
448
  ".portpkg" => "application/vnd.macports.portpkg",
449
+ ".pot" => "application/vnd.ms-powerpoint",
450
+ ".potm" => "application/vnd.ms-powerpoint.template.macroEnabled.12",
451
+ ".potx" => "application/vnd.openxmlformats-officedocument.presentationml.template",
452
+ ".ppa" => "application/vnd.ms-powerpoint",
453
+ ".ppam" => "application/vnd.ms-powerpoint.addin.macroEnabled.12",
447
454
  ".ppd" => "application/vnd.cups-ppd",
448
455
  ".ppm" => "image/x-portable-pixmap",
449
456
  ".pps" => "application/vnd.ms-powerpoint",
457
+ ".ppsm" => "application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
458
+ ".ppsx" => "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
450
459
  ".ppt" => "application/vnd.ms-powerpoint",
460
+ ".pptm" => "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
461
+ ".pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
451
462
  ".prc" => "application/vnd.palm",
452
463
  ".pre" => "application/vnd.lotus-freelance",
453
464
  ".prf" => "application/pics-rules",
@@ -535,6 +546,7 @@ module Rack
535
546
  ".spp" => "application/scvp-vp-response",
536
547
  ".spq" => "application/scvp-vp-request",
537
548
  ".src" => "application/x-wais-source",
549
+ ".srt" => "text/srt",
538
550
  ".srx" => "application/sparql-results+xml",
539
551
  ".sse" => "application/vnd.kodak-descriptor",
540
552
  ".ssf" => "application/vnd.epson.ssf",
@@ -569,6 +581,7 @@ module Rack
569
581
  ".tr" => "text/troff",
570
582
  ".tra" => "application/vnd.trueapp",
571
583
  ".trm" => "application/x-msterminal",
584
+ ".ts" => "video/mp2t",
572
585
  ".tsv" => "text/tab-separated-values",
573
586
  ".ttf" => "application/octet-stream",
574
587
  ".twd" => "application/vnd.simtech-mindmapper",
@@ -593,9 +606,11 @@ module Rack
593
606
  ".vrml" => "model/vrml",
594
607
  ".vsd" => "application/vnd.visio",
595
608
  ".vsf" => "application/vnd.vsf",
609
+ ".vtt" => "text/vtt",
596
610
  ".vtu" => "model/vnd.vtu",
597
611
  ".vxml" => "application/voicexml+xml",
598
612
  ".war" => "application/java-archive",
613
+ ".wasm" => "application/wasm",
599
614
  ".wav" => "audio/x-wav",
600
615
  ".wax" => "audio/x-ms-wax",
601
616
  ".wbmp" => "image/vnd.wap.wbmp",
@@ -638,8 +653,14 @@ module Rack
638
653
  ".xfdl" => "application/vnd.xfdl",
639
654
  ".xhtml" => "application/xhtml+xml",
640
655
  ".xif" => "image/vnd.xiff",
656
+ ".xla" => "application/vnd.ms-excel",
657
+ ".xlam" => "application/vnd.ms-excel.addin.macroEnabled.12",
641
658
  ".xls" => "application/vnd.ms-excel",
659
+ ".xlsb" => "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
642
660
  ".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
661
+ ".xlsm" => "application/vnd.ms-excel.sheet.macroEnabled.12",
662
+ ".xlt" => "application/vnd.ms-excel",
663
+ ".xltx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
643
664
  ".xml" => "application/xml",
644
665
  ".xo" => "application/vnd.olpc-sugar",
645
666
  ".xop" => "application/xop+xml",