rack 2.0.6 → 2.2.7

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 (190) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +735 -0
  3. data/CONTRIBUTING.md +136 -0
  4. data/{COPYING → MIT-LICENSE} +4 -2
  5. data/README.rdoc +163 -145
  6. data/Rakefile +37 -23
  7. data/{SPEC → SPEC.rdoc} +29 -5
  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 +7 -4
  15. data/lib/rack/auth/digest/md5.rb +13 -11
  16. data/lib/rack/auth/digest/nonce.rb +6 -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 +36 -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 +59 -34
  30. data/lib/rack/directory.rb +84 -64
  31. data/lib/rack/etag.rb +7 -4
  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 +15 -6
  41. data/lib/rack/handler.rb +7 -2
  42. data/lib/rack/head.rb +1 -1
  43. data/lib/rack/lint.rb +72 -26
  44. data/lib/rack/lobster.rb +10 -10
  45. data/lib/rack/lock.rb +2 -1
  46. data/lib/rack/logger.rb +2 -0
  47. data/lib/rack/media_type.rb +10 -5
  48. data/lib/rack/method_override.rb +5 -3
  49. data/lib/rack/mime.rb +9 -1
  50. data/lib/rack/mock.rb +97 -20
  51. data/lib/rack/multipart/generator.rb +17 -13
  52. data/lib/rack/multipart/parser.rb +74 -67
  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 +59 -30
  57. data/lib/rack/recursive.rb +7 -5
  58. data/lib/rack/reloader.rb +8 -4
  59. data/lib/rack/request.rb +222 -63
  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 +13 -9
  64. data/lib/rack/server.rb +95 -24
  65. data/lib/rack/session/abstract/id.rb +100 -22
  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 +18 -9
  69. data/lib/rack/show_exceptions.rb +21 -17
  70. data/lib/rack/show_status.rb +9 -9
  71. data/lib/rack/static.rb +23 -11
  72. data/lib/rack/tempfile_reaper.rb +1 -1
  73. data/lib/rack/urlmap.rb +13 -7
  74. data/lib/rack/utils.rb +127 -119
  75. data/lib/rack/version.rb +29 -0
  76. data/lib/rack.rb +67 -73
  77. data/rack.gemspec +40 -28
  78. metadata +39 -181
  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_null_byte +0 -7
  114. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  115. data/test/multipart/filename_with_single_quote +0 -7
  116. data/test/multipart/filename_with_unescaped_percentages +0 -6
  117. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  118. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  119. data/test/multipart/filename_with_unescaped_quotes +0 -6
  120. data/test/multipart/ie +0 -6
  121. data/test/multipart/invalid_character +0 -6
  122. data/test/multipart/mixed_files +0 -21
  123. data/test/multipart/nested +0 -10
  124. data/test/multipart/none +0 -9
  125. data/test/multipart/quoted +0 -15
  126. data/test/multipart/rack-logo.png +0 -0
  127. data/test/multipart/semicolon +0 -6
  128. data/test/multipart/text +0 -15
  129. data/test/multipart/three_files_three_fields +0 -31
  130. data/test/multipart/unity3d_wwwform +0 -11
  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 -89
  135. data/test/spec_auth_digest.rb +0 -260
  136. data/test/spec_body_proxy.rb +0 -85
  137. data/test/spec_builder.rb +0 -233
  138. data/test/spec_cascade.rb +0 -63
  139. data/test/spec_cgi.rb +0 -84
  140. data/test/spec_chunked.rb +0 -103
  141. data/test/spec_common_logger.rb +0 -95
  142. data/test/spec_conditional_get.rb +0 -103
  143. data/test/spec_config.rb +0 -23
  144. data/test/spec_content_length.rb +0 -86
  145. data/test/spec_content_type.rb +0 -46
  146. data/test/spec_deflater.rb +0 -375
  147. data/test/spec_directory.rb +0 -148
  148. data/test/spec_etag.rb +0 -108
  149. data/test/spec_events.rb +0 -133
  150. data/test/spec_fastcgi.rb +0 -85
  151. data/test/spec_file.rb +0 -264
  152. data/test/spec_handler.rb +0 -57
  153. data/test/spec_head.rb +0 -46
  154. data/test/spec_lint.rb +0 -515
  155. data/test/spec_lobster.rb +0 -59
  156. data/test/spec_lock.rb +0 -204
  157. data/test/spec_logger.rb +0 -24
  158. data/test/spec_media_type.rb +0 -42
  159. data/test/spec_method_override.rb +0 -110
  160. data/test/spec_mime.rb +0 -51
  161. data/test/spec_mock.rb +0 -359
  162. data/test/spec_multipart.rb +0 -722
  163. data/test/spec_null_logger.rb +0 -21
  164. data/test/spec_recursive.rb +0 -75
  165. data/test/spec_request.rb +0 -1398
  166. data/test/spec_response.rb +0 -510
  167. data/test/spec_rewindable_input.rb +0 -128
  168. data/test/spec_runtime.rb +0 -50
  169. data/test/spec_sendfile.rb +0 -125
  170. data/test/spec_server.rb +0 -193
  171. data/test/spec_session_abstract_id.rb +0 -31
  172. data/test/spec_session_abstract_session_hash.rb +0 -45
  173. data/test/spec_session_cookie.rb +0 -442
  174. data/test/spec_session_memcache.rb +0 -320
  175. data/test/spec_session_pool.rb +0 -210
  176. data/test/spec_show_exceptions.rb +0 -93
  177. data/test/spec_show_status.rb +0 -104
  178. data/test/spec_static.rb +0 -184
  179. data/test/spec_tempfile_reaper.rb +0 -64
  180. data/test/spec_thin.rb +0 -96
  181. data/test/spec_urlmap.rb +0 -237
  182. data/test/spec_utils.rb +0 -742
  183. data/test/spec_version.rb +0 -11
  184. data/test/spec_webrick.rb +0 -206
  185. data/test/static/another/index.html +0 -1
  186. data/test/static/foo.html +0 -1
  187. data/test/static/index.html +0 -1
  188. data/test/testrequest.rb +0 -78
  189. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  190. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/lib/rack/static.rb CHANGED
@@ -1,11 +1,10 @@
1
- require "rack/file"
2
- require "rack/utils"
1
+ # frozen_string_literal: true
3
2
 
4
3
  module Rack
5
4
 
6
5
  # The Rack::Static middleware intercepts requests for static files
7
6
  # (javascript files, images, stylesheets, etc) based on the url prefixes or
8
- # route mappings passed in the options, and serves them using a Rack::File
7
+ # route mappings passed in the options, and serves them using a Rack::Files
9
8
  # object. This allows a Rack stack to serve both static and dynamic content.
10
9
  #
11
10
  # Examples:
@@ -15,6 +14,11 @@ module Rack
15
14
  #
16
15
  # use Rack::Static, :urls => ["/media"]
17
16
  #
17
+ # Same as previous, but instead of returning 404 for missing files under
18
+ # /media, call the next middleware:
19
+ #
20
+ # use Rack::Static, :urls => ["/media"], :cascade => true
21
+ #
18
22
  # Serve all requests beginning with /css or /images from the folder "public"
19
23
  # in the current directory (ie public/css/* and public/images/*):
20
24
  #
@@ -82,24 +86,26 @@ module Rack
82
86
  # ]
83
87
  #
84
88
  class Static
89
+ (require_relative 'core_ext/regexp'; using ::Rack::RegexpExtensions) if RUBY_VERSION < '2.4'
85
90
 
86
- def initialize(app, options={})
91
+ def initialize(app, options = {})
87
92
  @app = app
88
93
  @urls = options[:urls] || ["/favicon.ico"]
89
94
  @index = options[:index]
90
95
  @gzip = options[:gzip]
96
+ @cascade = options[:cascade]
91
97
  root = options[:root] || Dir.pwd
92
98
 
93
99
  # HTTP Headers
94
100
  @header_rules = options[:header_rules] || []
95
101
  # Allow for legacy :cache_control option while prioritizing global header_rules setting
96
- @header_rules.unshift([:all, {CACHE_CONTROL => options[:cache_control]}]) if options[:cache_control]
102
+ @header_rules.unshift([:all, { CACHE_CONTROL => options[:cache_control] }]) if options[:cache_control]
97
103
 
98
- @file_server = Rack::File.new(root)
104
+ @file_server = Rack::Files.new(root)
99
105
  end
100
106
 
101
107
  def add_index_root?(path)
102
- @index && path =~ /\/$/
108
+ @index && route_file(path) && path.end_with?('/')
103
109
  end
104
110
 
105
111
  def overwrite_file_path(path)
@@ -120,7 +126,7 @@ module Rack
120
126
  if can_serve(path)
121
127
  if overwrite_file_path(path)
122
128
  env[PATH_INFO] = (add_index_root?(path) ? path + @index : @urls[path])
123
- elsif @gzip && env['HTTP_ACCEPT_ENCODING'] =~ /\bgzip\b/
129
+ elsif @gzip && env['HTTP_ACCEPT_ENCODING'] && /\bgzip\b/.match?(env['HTTP_ACCEPT_ENCODING'])
124
130
  path = env[PATH_INFO]
125
131
  env[PATH_INFO] += '.gz'
126
132
  response = @file_server.call(env)
@@ -128,6 +134,8 @@ module Rack
128
134
 
129
135
  if response[0] == 404
130
136
  response = nil
137
+ elsif response[0] == 304
138
+ # Do nothing, leave headers as is
131
139
  else
132
140
  if mime_type = Mime.mime_type(::File.extname(path), 'text/plain')
133
141
  response[1][CONTENT_TYPE] = mime_type
@@ -139,6 +147,10 @@ module Rack
139
147
  path = env[PATH_INFO]
140
148
  response ||= @file_server.call(env)
141
149
 
150
+ if @cascade && response[0] == 404
151
+ return @app.call(env)
152
+ end
153
+
142
154
  headers = response[1]
143
155
  applicable_rules(path).each do |rule, new_headers|
144
156
  new_headers.each { |field, content| headers[field] = content }
@@ -157,14 +169,14 @@ module Rack
157
169
  when :all
158
170
  true
159
171
  when :fonts
160
- path =~ /\.(?:ttf|otf|eot|woff2|woff|svg)\z/
172
+ /\.(?:ttf|otf|eot|woff2|woff|svg)\z/.match?(path)
161
173
  when String
162
174
  path = ::Rack::Utils.unescape(path)
163
175
  path.start_with?(rule) || path.start_with?('/' + rule)
164
176
  when Array
165
- path =~ /\.(#{rule.join('|')})\z/
177
+ /\.(#{rule.join('|')})\z/.match?(path)
166
178
  when Regexp
167
- path =~ rule
179
+ rule.match?(path)
168
180
  else
169
181
  false
170
182
  end
@@ -1,4 +1,4 @@
1
- require 'rack/body_proxy'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Rack
4
4
 
data/lib/rack/urlmap.rb CHANGED
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
1
5
  module Rack
2
6
  # Rack::URLMap takes a hash mapping urls or paths to apps, and
3
7
  # dispatches accordingly. Support for HTTP/1.1 host names exists if
@@ -12,17 +16,16 @@ module Rack
12
16
  # first, since they are most specific.
13
17
 
14
18
  class URLMap
15
- NEGATIVE_INFINITY = -1.0 / 0.0
16
- INFINITY = 1.0 / 0.0
17
-
18
19
  def initialize(map = {})
19
20
  remap(map)
20
21
  end
21
22
 
22
23
  def remap(map)
24
+ @known_hosts = Set[]
23
25
  @mapping = map.map { |location, app|
24
26
  if location =~ %r{\Ahttps?://(.*?)(/.*)}
25
27
  host, location = $1, $2
28
+ @known_hosts << host
26
29
  else
27
30
  host = nil
28
31
  end
@@ -32,11 +35,11 @@ module Rack
32
35
  end
33
36
 
34
37
  location = location.chomp('/')
35
- match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", nil, 'n')
38
+ match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", Regexp::NOENCODING)
36
39
 
37
40
  [host, location, match, app]
38
41
  }.sort_by do |(host, location, _, _)|
39
- [host ? -host.size : INFINITY, -location.size]
42
+ [host ? -host.size : Float::INFINITY, -location.size]
40
43
  end
41
44
  end
42
45
 
@@ -50,10 +53,13 @@ module Rack
50
53
  is_same_server = casecmp?(http_host, server_name) ||
51
54
  casecmp?(http_host, "#{server_name}:#{server_port}")
52
55
 
56
+ is_host_known = @known_hosts.include? http_host
57
+
53
58
  @mapping.each do |host, location, match, app|
54
59
  unless casecmp?(http_host, host) \
55
60
  || casecmp?(server_name, host) \
56
- || (!host && is_same_server)
61
+ || (!host && is_same_server) \
62
+ || (!host && !is_host_known) # If we don't have a matching host, default to the first without a specified host
57
63
  next
58
64
  end
59
65
 
@@ -68,7 +74,7 @@ module Rack
68
74
  return app.call(env)
69
75
  end
70
76
 
71
- [404, {CONTENT_TYPE => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{path}"]]
77
+ [404, { CONTENT_TYPE => "text/plain", "X-Cascade" => "pass" }, ["Not Found: #{path}"]]
72
78
 
73
79
  ensure
74
80
  env[PATH_INFO] = path