rack 1.6.13 → 2.0.1

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 (144) hide show
  1. checksums.yaml +5 -5
  2. data/COPYING +1 -1
  3. data/HISTORY.md +138 -8
  4. data/README.rdoc +17 -25
  5. data/Rakefile +6 -14
  6. data/SPEC +8 -9
  7. data/contrib/rack_logo.svg +164 -111
  8. data/example/protectedlobster.rb +1 -1
  9. data/example/protectedlobster.ru +1 -1
  10. data/lib/rack/auth/abstract/request.rb +5 -1
  11. data/lib/rack/auth/digest/params.rb +2 -3
  12. data/lib/rack/auth/digest/request.rb +1 -1
  13. data/lib/rack/body_proxy.rb +14 -9
  14. data/lib/rack/builder.rb +3 -3
  15. data/lib/rack/chunked.rb +5 -5
  16. data/lib/rack/{commonlogger.rb → common_logger.rb} +3 -3
  17. data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
  18. data/lib/rack/content_length.rb +2 -2
  19. data/lib/rack/deflater.rb +4 -4
  20. data/lib/rack/directory.rb +66 -54
  21. data/lib/rack/etag.rb +4 -3
  22. data/lib/rack/events.rb +154 -0
  23. data/lib/rack/file.rb +63 -39
  24. data/lib/rack/handler/cgi.rb +15 -16
  25. data/lib/rack/handler/fastcgi.rb +13 -14
  26. data/lib/rack/handler/lsws.rb +11 -11
  27. data/lib/rack/handler/scgi.rb +15 -15
  28. data/lib/rack/handler/thin.rb +3 -0
  29. data/lib/rack/handler/webrick.rb +22 -24
  30. data/lib/rack/handler.rb +3 -25
  31. data/lib/rack/head.rb +15 -17
  32. data/lib/rack/lint.rb +38 -38
  33. data/lib/rack/lobster.rb +1 -1
  34. data/lib/rack/lock.rb +6 -10
  35. data/lib/rack/logger.rb +2 -2
  36. data/lib/rack/media_type.rb +38 -0
  37. data/lib/rack/{methodoverride.rb → method_override.rb} +4 -11
  38. data/lib/rack/mime.rb +18 -5
  39. data/lib/rack/mock.rb +35 -53
  40. data/lib/rack/multipart/generator.rb +5 -5
  41. data/lib/rack/multipart/parser.rb +272 -158
  42. data/lib/rack/multipart/uploaded_file.rb +1 -2
  43. data/lib/rack/multipart.rb +35 -6
  44. data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
  45. data/lib/rack/query_parser.rb +192 -0
  46. data/lib/rack/recursive.rb +8 -8
  47. data/lib/rack/request.rb +383 -307
  48. data/lib/rack/response.rb +129 -56
  49. data/lib/rack/rewindable_input.rb +1 -12
  50. data/lib/rack/runtime.rb +10 -18
  51. data/lib/rack/sendfile.rb +5 -7
  52. data/lib/rack/server.rb +31 -25
  53. data/lib/rack/session/abstract/id.rb +95 -135
  54. data/lib/rack/session/cookie.rb +26 -28
  55. data/lib/rack/session/memcache.rb +8 -14
  56. data/lib/rack/session/pool.rb +14 -21
  57. data/lib/rack/show_exceptions.rb +386 -0
  58. data/lib/rack/{showstatus.rb → show_status.rb} +3 -3
  59. data/lib/rack/static.rb +30 -5
  60. data/lib/rack/tempfile_reaper.rb +2 -2
  61. data/lib/rack/urlmap.rb +15 -14
  62. data/lib/rack/utils.rb +135 -210
  63. data/lib/rack.rb +70 -21
  64. data/rack.gemspec +7 -5
  65. data/test/builder/an_underscore_app.rb +5 -0
  66. data/test/builder/options.ru +1 -1
  67. data/test/cgi/test.fcgi +1 -0
  68. data/test/cgi/test.gz +0 -0
  69. data/test/helper.rb +34 -0
  70. data/test/multipart/filename_with_encoded_words +7 -0
  71. data/test/multipart/{filename_with_null_byte → filename_with_single_quote} +1 -1
  72. data/test/multipart/quoted +15 -0
  73. data/test/multipart/rack-logo.png +0 -0
  74. data/test/multipart/unity3d_wwwform +11 -0
  75. data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
  76. data/test/spec_auth_basic.rb +27 -19
  77. data/test/spec_auth_digest.rb +47 -46
  78. data/test/spec_body_proxy.rb +27 -27
  79. data/test/spec_builder.rb +51 -41
  80. data/test/spec_cascade.rb +24 -22
  81. data/test/spec_cgi.rb +49 -67
  82. data/test/spec_chunked.rb +36 -34
  83. data/test/{spec_commonlogger.rb → spec_common_logger.rb} +23 -21
  84. data/test/{spec_conditionalget.rb → spec_conditional_get.rb} +29 -28
  85. data/test/spec_config.rb +3 -2
  86. data/test/spec_content_length.rb +18 -17
  87. data/test/spec_content_type.rb +13 -12
  88. data/test/spec_deflater.rb +66 -40
  89. data/test/spec_directory.rb +87 -27
  90. data/test/spec_etag.rb +32 -31
  91. data/test/spec_events.rb +133 -0
  92. data/test/spec_fastcgi.rb +50 -72
  93. data/test/spec_file.rb +107 -77
  94. data/test/spec_handler.rb +19 -34
  95. data/test/spec_head.rb +15 -14
  96. data/test/spec_lint.rb +162 -197
  97. data/test/spec_lobster.rb +24 -23
  98. data/test/spec_lock.rb +69 -39
  99. data/test/spec_logger.rb +4 -3
  100. data/test/spec_media_type.rb +42 -0
  101. data/test/spec_method_override.rb +83 -0
  102. data/test/spec_mime.rb +19 -19
  103. data/test/spec_mock.rb +196 -151
  104. data/test/spec_multipart.rb +317 -201
  105. data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
  106. data/test/spec_recursive.rb +17 -14
  107. data/test/spec_request.rb +768 -607
  108. data/test/spec_response.rb +214 -111
  109. data/test/spec_rewindable_input.rb +50 -40
  110. data/test/spec_runtime.rb +11 -10
  111. data/test/spec_sendfile.rb +30 -35
  112. data/test/spec_server.rb +78 -52
  113. data/test/spec_session_abstract_id.rb +11 -33
  114. data/test/spec_session_abstract_session_hash.rb +28 -0
  115. data/test/spec_session_cookie.rb +97 -65
  116. data/test/spec_session_memcache.rb +63 -101
  117. data/test/spec_session_pool.rb +48 -84
  118. data/test/spec_show_exceptions.rb +80 -0
  119. data/test/{spec_showstatus.rb → spec_show_status.rb} +36 -35
  120. data/test/spec_static.rb +71 -32
  121. data/test/spec_tempfile_reaper.rb +11 -10
  122. data/test/spec_thin.rb +55 -50
  123. data/test/spec_urlmap.rb +79 -78
  124. data/test/spec_utils.rb +441 -346
  125. data/test/spec_version.rb +2 -8
  126. data/test/spec_webrick.rb +91 -67
  127. data/test/static/foo.html +1 -0
  128. data/test/testrequest.rb +1 -1
  129. data/test/unregistered_handler/rack/handler/unregistered.rb +1 -1
  130. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +1 -1
  131. metadata +103 -69
  132. data/KNOWN-ISSUES +0 -44
  133. data/lib/rack/backports/uri/common_18.rb +0 -56
  134. data/lib/rack/backports/uri/common_192.rb +0 -52
  135. data/lib/rack/backports/uri/common_193.rb +0 -29
  136. data/lib/rack/handler/evented_mongrel.rb +0 -8
  137. data/lib/rack/handler/mongrel.rb +0 -106
  138. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  139. data/lib/rack/showexceptions.rb +0 -387
  140. data/lib/rack/utils/okjson.rb +0 -600
  141. data/test/spec_methodoverride.rb +0 -111
  142. data/test/spec_mongrel.rb +0 -182
  143. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  144. data/test/spec_showexceptions.rb +0 -98
@@ -35,24 +35,24 @@ module Rack
35
35
  env = Hash[request]
36
36
  env.delete "HTTP_CONTENT_TYPE"
37
37
  env.delete "HTTP_CONTENT_LENGTH"
38
- env["REQUEST_PATH"], env[QUERY_STRING] = env["REQUEST_URI"].split('?', 2)
39
- env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
40
- env[PATH_INFO] = env["REQUEST_PATH"]
41
- env["QUERY_STRING"] ||= ""
42
- env["SCRIPT_NAME"] = ""
38
+ env[REQUEST_PATH], env[QUERY_STRING] = env["REQUEST_URI"].split('?', 2)
39
+ env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
40
+ env[PATH_INFO] = env[REQUEST_PATH]
41
+ env[QUERY_STRING] ||= ""
42
+ env[SCRIPT_NAME] = ""
43
43
 
44
- rack_input = StringIO.new(input_body)
45
- rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
44
+ rack_input = StringIO.new(input_body, encoding: Encoding::BINARY)
46
45
 
47
- env.update({"rack.version" => Rack::VERSION,
48
- "rack.input" => rack_input,
49
- "rack.errors" => $stderr,
50
- "rack.multithread" => true,
51
- "rack.multiprocess" => true,
52
- "rack.run_once" => false,
46
+ env.update(
47
+ RACK_VERSION => Rack::VERSION,
48
+ RACK_INPUT => rack_input,
49
+ RACK_ERRORS => $stderr,
50
+ RACK_MULTITHREAD => true,
51
+ RACK_MULTIPROCESS => true,
52
+ RACK_RUNONCE => false,
53
+ RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[HTTPS]) ? "https" : "http"
54
+ )
53
55
 
54
- "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http"
55
- })
56
56
  status, headers, body = app.call(env)
57
57
  begin
58
58
  socket.write("Status: #{status}\r\n")
@@ -1,4 +1,7 @@
1
1
  require "thin"
2
+ require "thin/server"
3
+ require "thin/logging"
4
+ require "thin/backends/tcp_server"
2
5
  require "rack/content_length"
3
6
  require "rack/chunked"
4
7
 
@@ -3,7 +3,7 @@ require 'stringio'
3
3
  require 'rack/content_length'
4
4
 
5
5
  # This monkey patch allows for applications to perform their own chunking
6
- # through WEBrick::HTTPResponse iff rack is set to true.
6
+ # through WEBrick::HTTPResponse if rack is set to true.
7
7
  class WEBrick::HTTPResponse
8
8
  attr_accessor :rack
9
9
 
@@ -24,7 +24,7 @@ module Rack
24
24
  class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet
25
25
  def self.run(app, options={})
26
26
  environment = ENV['RACK_ENV'] || 'development'
27
- default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
27
+ default_host = environment == 'development' ? 'localhost' : nil
28
28
 
29
29
  options[:BindAddress] = options.delete(:Host) || default_host
30
30
  options[:Port] ||= 8080
@@ -60,36 +60,34 @@ module Rack
60
60
  env.delete_if { |k, v| v.nil? }
61
61
 
62
62
  rack_input = StringIO.new(req.body.to_s)
63
- rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
64
-
65
- env.update({"rack.version" => Rack::VERSION,
66
- "rack.input" => rack_input,
67
- "rack.errors" => $stderr,
68
-
69
- "rack.multithread" => true,
70
- "rack.multiprocess" => false,
71
- "rack.run_once" => false,
72
-
73
- "rack.url_scheme" => ["yes", "on", "1"].include?(env["HTTPS"]) ? "https" : "http",
74
-
75
- "rack.hijack?" => true,
76
- "rack.hijack" => lambda { raise NotImplementedError, "only partial hijack is supported."},
77
- "rack.hijack_io" => nil,
78
- })
79
-
80
- env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"]
63
+ rack_input.set_encoding(Encoding::BINARY)
64
+
65
+ env.update(
66
+ RACK_VERSION => Rack::VERSION,
67
+ RACK_INPUT => rack_input,
68
+ RACK_ERRORS => $stderr,
69
+ RACK_MULTITHREAD => true,
70
+ RACK_MULTIPROCESS => false,
71
+ RACK_RUNONCE => false,
72
+ RACK_URL_SCHEME => ["yes", "on", "1"].include?(env[HTTPS]) ? "https" : "http",
73
+ RACK_IS_HIJACK => true,
74
+ RACK_HIJACK => lambda { raise NotImplementedError, "only partial hijack is supported."},
75
+ RACK_HIJACK_IO => nil
76
+ )
77
+
78
+ env[HTTP_VERSION] ||= env[SERVER_PROTOCOL]
81
79
  env[QUERY_STRING] ||= ""
82
80
  unless env[PATH_INFO] == ""
83
- path, n = req.request_uri.path, env["SCRIPT_NAME"].length
81
+ path, n = req.request_uri.path, env[SCRIPT_NAME].length
84
82
  env[PATH_INFO] = path[n, path.length-n]
85
83
  end
86
- env["REQUEST_PATH"] ||= [env["SCRIPT_NAME"], env[PATH_INFO]].join
84
+ env[REQUEST_PATH] ||= [env[SCRIPT_NAME], env[PATH_INFO]].join
87
85
 
88
86
  status, headers, body = @app.call(env)
89
87
  begin
90
88
  res.status = status.to_i
91
89
  headers.each { |k, vs|
92
- next if k.downcase == "rack.hijack"
90
+ next if k.downcase == RACK_HIJACK
93
91
 
94
92
  if k.downcase == "set-cookie"
95
93
  res.cookies.concat vs.split("\n")
@@ -100,7 +98,7 @@ module Rack
100
98
  end
101
99
  }
102
100
 
103
- io_lambda = headers["rack.hijack"]
101
+ io_lambda = headers[RACK_HIJACK]
104
102
  if io_lambda
105
103
  rd, wr = IO.pipe
106
104
  res.body = rd
data/lib/rack/handler.rb CHANGED
@@ -19,25 +19,13 @@ module Rack
19
19
  if klass = @handlers[server]
20
20
  klass.split("::").inject(Object) { |o, x| o.const_get(x) }
21
21
  else
22
- _const_get(server, false)
22
+ const_get(server, false)
23
23
  end
24
24
 
25
25
  rescue NameError => name_error
26
26
  raise load_error || name_error
27
27
  end
28
28
 
29
- begin
30
- ::Object.const_get("Object", false)
31
- def self._const_get(str, inherit = true)
32
- const_get(str, inherit)
33
- end
34
- rescue
35
- def self._const_get(str, inherit = true)
36
- const_get(str)
37
- end
38
- end
39
-
40
-
41
29
  # Select first available Rack handler given an `Array` of server names.
42
30
  # Raises `LoadError` if no handler was found.
43
31
  #
@@ -55,20 +43,16 @@ module Rack
55
43
  raise LoadError, "Couldn't find handler for: #{server_names.join(', ')}."
56
44
  end
57
45
 
58
- def self.default(options = {})
46
+ def self.default
59
47
  # Guess.
60
48
  if ENV.include?("PHP_FCGI_CHILDREN")
61
- # We already speak FastCGI
62
- options.delete :File
63
- options.delete :Port
64
-
65
49
  Rack::Handler::FastCGI
66
50
  elsif ENV.include?(REQUEST_METHOD)
67
51
  Rack::Handler::CGI
68
52
  elsif ENV.include?("RACK_HANDLER")
69
53
  self.get(ENV["RACK_HANDLER"])
70
54
  else
71
- pick ['thin', 'puma', 'webrick']
55
+ pick ['puma', 'thin', 'webrick']
72
56
  end
73
57
  end
74
58
 
@@ -100,9 +84,6 @@ module Rack
100
84
 
101
85
  autoload :CGI, "rack/handler/cgi"
102
86
  autoload :FastCGI, "rack/handler/fastcgi"
103
- autoload :Mongrel, "rack/handler/mongrel"
104
- autoload :EventedMongrel, "rack/handler/evented_mongrel"
105
- autoload :SwiftipliedMongrel, "rack/handler/swiftiplied_mongrel"
106
87
  autoload :WEBrick, "rack/handler/webrick"
107
88
  autoload :LSWS, "rack/handler/lsws"
108
89
  autoload :SCGI, "rack/handler/scgi"
@@ -110,9 +91,6 @@ module Rack
110
91
 
111
92
  register 'cgi', 'Rack::Handler::CGI'
112
93
  register 'fastcgi', 'Rack::Handler::FastCGI'
113
- register 'mongrel', 'Rack::Handler::Mongrel'
114
- register 'emongrel', 'Rack::Handler::EventedMongrel'
115
- register 'smongrel', 'Rack::Handler::SwiftipliedMongrel'
116
94
  register 'webrick', 'Rack::Handler::WEBrick'
117
95
  register 'lsws', 'Rack::Handler::LSWS'
118
96
  register 'scgi', 'Rack::Handler::SCGI'
data/lib/rack/head.rb CHANGED
@@ -1,27 +1,25 @@
1
1
  require 'rack/body_proxy'
2
2
 
3
3
  module Rack
4
-
5
- class Head
6
4
  # Rack::Head returns an empty body for all HEAD requests. It leaves
7
5
  # all other requests unchanged.
8
- def initialize(app)
9
- @app = app
10
- end
6
+ class Head
7
+ def initialize(app)
8
+ @app = app
9
+ end
11
10
 
12
- def call(env)
13
- status, headers, body = @app.call(env)
11
+ def call(env)
12
+ status, headers, body = @app.call(env)
14
13
 
15
- if env[REQUEST_METHOD] == HEAD
16
- [
17
- status, headers, Rack::BodyProxy.new([]) do
18
- body.close if body.respond_to? :close
19
- end
20
- ]
21
- else
22
- [status, headers, body]
14
+ if env[REQUEST_METHOD] == HEAD
15
+ [
16
+ status, headers, Rack::BodyProxy.new([]) do
17
+ body.close if body.respond_to? :close
18
+ end
19
+ ]
20
+ else
21
+ [status, headers, body]
22
+ end
23
23
  end
24
24
  end
25
25
  end
26
-
27
- end
data/lib/rack/lint.rb CHANGED
@@ -15,8 +15,8 @@ module Rack
15
15
 
16
16
  class LintError < RuntimeError; end
17
17
  module Assertion
18
- def assert(message, &block)
19
- unless block.call
18
+ def assert(message)
19
+ unless yield
20
20
  raise LintError, message
21
21
  end
22
22
  end
@@ -42,8 +42,8 @@ module Rack
42
42
  assert("No env given") { env }
43
43
  check_env env
44
44
 
45
- env['rack.input'] = InputWrapper.new(env['rack.input'])
46
- env['rack.errors'] = ErrorWrapper.new(env['rack.errors'])
45
+ env[RACK_INPUT] = InputWrapper.new(env[RACK_INPUT])
46
+ env[RACK_ERRORS] = ErrorWrapper.new(env[RACK_ERRORS])
47
47
 
48
48
  ## and returns an Array of exactly three values:
49
49
  status, headers, @body = @app.call(env)
@@ -57,7 +57,7 @@ module Rack
57
57
  ## and the *body*.
58
58
  check_content_type status, headers
59
59
  check_content_length status, headers
60
- @head_request = env[REQUEST_METHOD] == "HEAD"
60
+ @head_request = env[REQUEST_METHOD] == HEAD
61
61
  [status, headers, self]
62
62
  end
63
63
 
@@ -95,7 +95,7 @@ module Rack
95
95
  ## empty string, if the request URL targets
96
96
  ## the application root and does not have a
97
97
  ## trailing slash. This value may be
98
- ## percent-encoded when I originating from
98
+ ## percent-encoded when originating from
99
99
  ## a URL.
100
100
 
101
101
  ## <tt>QUERY_STRING</tt>:: The portion of the request URL that
@@ -177,7 +177,7 @@ module Rack
177
177
  ## <tt>rack.session</tt>:: A hash like interface for storing
178
178
  ## request session data.
179
179
  ## The store must implement:
180
- if session = env['rack.session']
180
+ if session = env[RACK_SESSION]
181
181
  ## store(key, value) (aliased as []=);
182
182
  assert("session #{session.inspect} must respond to store and []=") {
183
183
  session.respond_to?(:store) && session.respond_to?(:[]=)
@@ -201,7 +201,7 @@ module Rack
201
201
 
202
202
  ## <tt>rack.logger</tt>:: A common object interface for logging messages.
203
203
  ## The object must implement:
204
- if logger = env['rack.logger']
204
+ if logger = env[RACK_LOGGER]
205
205
  ## info(message, &block)
206
206
  assert("logger #{logger.inspect} must respond to info") {
207
207
  logger.respond_to?(:info)
@@ -229,16 +229,16 @@ module Rack
229
229
  end
230
230
 
231
231
  ## <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']
232
+ if bufsize = env[RACK_MULTIPART_BUFFER_SIZE]
233
233
  assert("rack.multipart.buffer_size must be an Integer > 0 if specified") {
234
234
  bufsize.is_a?(Integer) && bufsize > 0
235
235
  }
236
236
  end
237
237
 
238
238
  ## <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']
239
+ if tempfile_factory = env[RACK_MULTIPART_TEMPFILE_FACTORY]
240
240
  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|
241
+ env[RACK_MULTIPART_TEMPFILE_FACTORY] = lambda do |filename, content_type|
242
242
  io = tempfile_factory.call(filename, content_type)
243
243
  assert("rack.multipart.tempfile_factory return value must respond to #<<") { io.respond_to?(:<<) }
244
244
  io
@@ -279,37 +279,37 @@ module Rack
279
279
  ## There are the following restrictions:
280
280
 
281
281
  ## * <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
282
+ assert("rack.version must be an Array, was #{env[RACK_VERSION].class}") {
283
+ env[RACK_VERSION].kind_of? Array
284
284
  }
285
285
  ## * <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"]
286
+ assert("rack.url_scheme unknown: #{env[RACK_URL_SCHEME].inspect}") {
287
+ %w[http https].include?(env[RACK_URL_SCHEME])
288
288
  }
289
289
 
290
290
  ## * There must be a valid input stream in <tt>rack.input</tt>.
291
- check_input env["rack.input"]
291
+ check_input env[RACK_INPUT]
292
292
  ## * There must be a valid error stream in <tt>rack.errors</tt>.
293
- check_error env["rack.errors"]
293
+ check_error env[RACK_ERRORS]
294
294
  ## * There may be a valid hijack stream in <tt>rack.hijack_io</tt>
295
295
  check_hijack env
296
296
 
297
297
  ## * The <tt>REQUEST_METHOD</tt> must be a valid token.
298
298
  assert("REQUEST_METHOD unknown: #{env[REQUEST_METHOD]}") {
299
- env["REQUEST_METHOD"] =~ /\A[0-9A-Za-z!\#$%&'*+.^_`|~-]+\z/
299
+ env[REQUEST_METHOD] =~ /\A[0-9A-Za-z!\#$%&'*+.^_`|~-]+\z/
300
300
  }
301
301
 
302
302
  ## * The <tt>SCRIPT_NAME</tt>, if non-empty, must start with <tt>/</tt>
303
303
  assert("SCRIPT_NAME must start with /") {
304
- !env.include?("SCRIPT_NAME") ||
305
- env["SCRIPT_NAME"] == "" ||
306
- env["SCRIPT_NAME"] =~ /\A\//
304
+ !env.include?(SCRIPT_NAME) ||
305
+ env[SCRIPT_NAME] == "" ||
306
+ env[SCRIPT_NAME] =~ /\A\//
307
307
  }
308
308
  ## * The <tt>PATH_INFO</tt>, if non-empty, must start with <tt>/</tt>
309
309
  assert("PATH_INFO must start with /") {
310
- !env.include?("PATH_INFO") ||
311
- env["PATH_INFO"] == "" ||
312
- env["PATH_INFO"] =~ /\A\//
310
+ !env.include?(PATH_INFO) ||
311
+ env[PATH_INFO] == "" ||
312
+ env[PATH_INFO] =~ /\A\//
313
313
  }
314
314
  ## * The <tt>CONTENT_LENGTH</tt>, if given, must consist of digits only.
315
315
  assert("Invalid CONTENT_LENGTH: #{env["CONTENT_LENGTH"]}") {
@@ -320,11 +320,11 @@ module Rack
320
320
  ## set. <tt>PATH_INFO</tt> should be <tt>/</tt> if
321
321
  ## <tt>SCRIPT_NAME</tt> is empty.
322
322
  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"]
323
+ env[SCRIPT_NAME] || env[PATH_INFO]
324
324
  }
325
325
  ## <tt>SCRIPT_NAME</tt> never should be <tt>/</tt>, but instead be empty.
326
326
  assert("SCRIPT_NAME cannot be '/', make it '' and PATH_INFO '/'") {
327
- env["SCRIPT_NAME"] != "/"
327
+ env[SCRIPT_NAME] != "/"
328
328
  }
329
329
  end
330
330
 
@@ -518,11 +518,11 @@ module Rack
518
518
  #
519
519
  ## ==== Request (before status)
520
520
  def check_hijack(env)
521
- if env['rack.hijack?']
521
+ if env[RACK_IS_HIJACK]
522
522
  ## If rack.hijack? is true then rack.hijack must respond to #call.
523
- original_hijack = env['rack.hijack']
523
+ original_hijack = env[RACK_HIJACK]
524
524
  assert("rack.hijack must respond to call") { original_hijack.respond_to?(:call) }
525
- env['rack.hijack'] = proc do
525
+ env[RACK_HIJACK] = proc do
526
526
  ## rack.hijack must return the io that will also be assigned (or is
527
527
  ## already present, in rack.hijack_io.
528
528
  io = original_hijack.call
@@ -548,16 +548,16 @@ module Rack
548
548
  ## hijack_io to provide additional features to users. The purpose of
549
549
  ## rack.hijack is for Rack to "get out of the way", as such, Rack only
550
550
  ## provides the minimum of specification and support.
551
- env['rack.hijack_io'] = HijackWrapper.new(env['rack.hijack_io'])
551
+ env[RACK_HIJACK_IO] = HijackWrapper.new(env[RACK_HIJACK_IO])
552
552
  io
553
553
  end
554
554
  else
555
555
  ##
556
556
  ## 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? }
557
+ assert("rack.hijack? is false, but rack.hijack is present") { env[RACK_HIJACK].nil? }
558
558
  ##
559
559
  ## 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? }
560
+ assert("rack.hijack? is false, but rack.hijack_io is present") { env[RACK_HIJACK_IO].nil? }
561
561
  end
562
562
  end
563
563
 
@@ -587,12 +587,12 @@ module Rack
587
587
  ## Servers must ignore the <tt>body</tt> part of the response tuple when
588
588
  ## the <tt>rack.hijack</tt> response API is in use.
589
589
 
590
- if env['rack.hijack?'] && headers['rack.hijack']
590
+ if env[RACK_IS_HIJACK] && headers[RACK_HIJACK]
591
591
  assert('rack.hijack header must respond to #call') {
592
- headers['rack.hijack'].respond_to? :call
592
+ headers[RACK_HIJACK].respond_to? :call
593
593
  }
594
- original_hijack = headers['rack.hijack']
595
- headers['rack.hijack'] = proc do |io|
594
+ original_hijack = headers[RACK_HIJACK]
595
+ headers[RACK_HIJACK] = proc do |io|
596
596
  original_hijack.call HijackWrapper.new(io)
597
597
  end
598
598
  else
@@ -600,7 +600,7 @@ module Rack
600
600
  ## The special response header <tt>rack.hijack</tt> must only be set
601
601
  ## if the request env has <tt>rack.hijack?</tt> <tt>true</tt>.
602
602
  assert('rack.hijack header must not be present if server does not support hijacking') {
603
- headers['rack.hijack'].nil?
603
+ headers[RACK_HIJACK].nil?
604
604
  }
605
605
  end
606
606
  end
@@ -710,7 +710,7 @@ module Rack
710
710
  assert("Body yielded non-string value #{part.inspect}") {
711
711
  part.kind_of? String
712
712
  }
713
- bytes += Rack::Utils.bytesize(part)
713
+ bytes += part.bytesize
714
714
  yield part
715
715
  }
716
716
  verify_content_length(bytes)
data/lib/rack/lobster.rb CHANGED
@@ -63,7 +63,7 @@ end
63
63
 
64
64
  if $0 == __FILE__
65
65
  require 'rack'
66
- require 'rack/showexceptions'
66
+ require 'rack/show_exceptions'
67
67
  Rack::Server.start(
68
68
  :app => Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), :Port => 9292
69
69
  )
data/lib/rack/lock.rb CHANGED
@@ -5,22 +5,18 @@ module Rack
5
5
  # Rack::Lock locks every request inside a mutex, so that every request
6
6
  # will effectively be executed synchronously.
7
7
  class Lock
8
- FLAG = 'rack.multithread'.freeze
9
-
10
8
  def initialize(app, mutex = Mutex.new)
11
9
  @app, @mutex = app, mutex
12
10
  end
13
11
 
14
12
  def call(env)
15
- old, env[FLAG] = env[FLAG], false
16
13
  @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
14
+ begin
15
+ response = @app.call(env.merge(RACK_MULTITHREAD => false))
16
+ returned = response << BodyProxy.new(response.pop) { @mutex.unlock }
17
+ ensure
18
+ @mutex.unlock unless returned
19
+ end
24
20
  end
25
21
  end
26
22
  end
data/lib/rack/logger.rb CHANGED
@@ -8,10 +8,10 @@ module Rack
8
8
  end
9
9
 
10
10
  def call(env)
11
- logger = ::Logger.new(env['rack.errors'])
11
+ logger = ::Logger.new(env[RACK_ERRORS])
12
12
  logger.level = @level
13
13
 
14
- env['rack.logger'] = logger
14
+ env[RACK_LOGGER] = logger
15
15
  @app.call(env)
16
16
  end
17
17
  end
@@ -0,0 +1,38 @@
1
+ module Rack
2
+ # Rack::MediaType parse media type and parameters out of content_type string
3
+
4
+ class MediaType
5
+ SPLIT_PATTERN = %r{\s*[;,]\s*}
6
+
7
+ class << self
8
+ # The media type (type/subtype) portion of the CONTENT_TYPE header
9
+ # without any media type parameters. e.g., when CONTENT_TYPE is
10
+ # "text/plain;charset=utf-8", the media-type is "text/plain".
11
+ #
12
+ # For more information on the use of media types in HTTP, see:
13
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
14
+ def type(content_type)
15
+ return nil unless content_type
16
+ content_type.split(SPLIT_PATTERN, 2).first.downcase
17
+ end
18
+
19
+ # The media type parameters provided in CONTENT_TYPE as a Hash, or
20
+ # an empty Hash if no CONTENT_TYPE or media-type parameters were
21
+ # provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8",
22
+ # this method responds with the following Hash:
23
+ # { 'charset' => 'utf-8' }
24
+ def params(content_type)
25
+ return {} if content_type.nil?
26
+ Hash[*content_type.split(SPLIT_PATTERN)[1..-1].
27
+ collect { |s| s.split('=', 2) }.
28
+ map { |k,v| [k.downcase, strip_doublequotes(v)] }.flatten]
29
+ end
30
+
31
+ private
32
+
33
+ def strip_doublequotes(str)
34
+ (str[0] == ?" && str[-1] == ?") ? str[1..-2] : str
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,10 +1,10 @@
1
1
  module Rack
2
2
  class MethodOverride
3
- HTTP_METHODS = %w(GET HEAD PUT POST DELETE OPTIONS PATCH LINK UNLINK)
3
+ HTTP_METHODS = %w[GET HEAD PUT POST DELETE OPTIONS PATCH LINK UNLINK]
4
4
 
5
5
  METHOD_OVERRIDE_PARAM_KEY = "_method".freeze
6
6
  HTTP_METHOD_OVERRIDE_HEADER = "HTTP_X_HTTP_METHOD_OVERRIDE".freeze
7
- ALLOWED_METHODS = ["POST"]
7
+ ALLOWED_METHODS = %w[POST]
8
8
 
9
9
  def initialize(app)
10
10
  @app = app
@@ -14,7 +14,7 @@ module Rack
14
14
  if allowed_methods.include?(env[REQUEST_METHOD])
15
15
  method = method_override(env)
16
16
  if HTTP_METHODS.include?(method)
17
- env["rack.methodoverride.original_method"] = env[REQUEST_METHOD]
17
+ env[RACK_METHODOVERRIDE_ORIGINAL_METHOD] = env[REQUEST_METHOD]
18
18
  env[REQUEST_METHOD] = method
19
19
  end
20
20
  end
@@ -26,11 +26,7 @@ module Rack
26
26
  req = Request.new(env)
27
27
  method = method_override_param(req) ||
28
28
  env[HTTP_METHOD_OVERRIDE_HEADER]
29
- begin
30
- method.to_s.upcase
31
- rescue ArgumentError
32
- env["rack.errors"].puts "Invalid string for method"
33
- end
29
+ method.to_s.upcase
34
30
  end
35
31
 
36
32
  private
@@ -42,9 +38,6 @@ module Rack
42
38
  def method_override_param(req)
43
39
  req.POST[METHOD_OVERRIDE_PARAM_KEY]
44
40
  rescue Utils::InvalidParameterError, Utils::ParameterTypeError
45
- req.env["rack.errors"].puts "Invalid or incomplete POST params"
46
- rescue EOFError
47
- req.env["rack.errors"].puts "Bad request content body"
48
41
  end
49
42
  end
50
43
  end
data/lib/rack/mime.rb CHANGED
@@ -45,11 +45,6 @@ module Rack
45
45
  #
46
46
  # N.B. On Ubuntu the mime.types file does not include the leading period, so
47
47
  # 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
48
 
54
49
  MIME_TYPES = {
55
50
  ".123" => "application/vnd.lotus-1-2-3",
@@ -154,8 +149,11 @@ module Rack
154
149
  ".dmg" => "application/octet-stream",
155
150
  ".dna" => "application/vnd.dna",
156
151
  ".doc" => "application/msword",
152
+ ".docm" => "application/vnd.ms-word.document.macroEnabled.12",
157
153
  ".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
158
154
  ".dot" => "application/msword",
155
+ ".dotm" => "application/vnd.ms-word.template.macroEnabled.12",
156
+ ".dotx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
159
157
  ".dp" => "application/vnd.osgi.dp",
160
158
  ".dpg" => "application/vnd.dpgraph",
161
159
  ".dsc" => "text/prs.lines.tag",
@@ -444,10 +442,19 @@ module Rack
444
442
  ".pnm" => "image/x-portable-anymap",
445
443
  ".pntg" => "image/x-macpaint",
446
444
  ".portpkg" => "application/vnd.macports.portpkg",
445
+ ".pot" => "application/vnd.ms-powerpoint",
446
+ ".potm" => "application/vnd.ms-powerpoint.template.macroEnabled.12",
447
+ ".potx" => "application/vnd.openxmlformats-officedocument.presentationml.template",
448
+ ".ppa" => "application/vnd.ms-powerpoint",
449
+ ".ppam" => "application/vnd.ms-powerpoint.addin.macroEnabled.12",
447
450
  ".ppd" => "application/vnd.cups-ppd",
448
451
  ".ppm" => "image/x-portable-pixmap",
449
452
  ".pps" => "application/vnd.ms-powerpoint",
453
+ ".ppsm" => "application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
454
+ ".ppsx" => "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
450
455
  ".ppt" => "application/vnd.ms-powerpoint",
456
+ ".pptm" => "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
457
+ ".pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
451
458
  ".prc" => "application/vnd.palm",
452
459
  ".pre" => "application/vnd.lotus-freelance",
453
460
  ".prf" => "application/pics-rules",
@@ -638,8 +645,14 @@ module Rack
638
645
  ".xfdl" => "application/vnd.xfdl",
639
646
  ".xhtml" => "application/xhtml+xml",
640
647
  ".xif" => "image/vnd.xiff",
648
+ ".xla" => "application/vnd.ms-excel",
649
+ ".xlam" => "application/vnd.ms-excel.addin.macroEnabled.12",
641
650
  ".xls" => "application/vnd.ms-excel",
651
+ ".xlsb" => "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
642
652
  ".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
653
+ ".xlsm" => "application/vnd.ms-excel.sheet.macroEnabled.12",
654
+ ".xlt" => "application/vnd.ms-excel",
655
+ ".xltx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
643
656
  ".xml" => "application/xml",
644
657
  ".xo" => "application/vnd.olpc-sugar",
645
658
  ".xop" => "application/xop+xml",