rack 1.0.1 → 2.2.21

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 (147) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +829 -0
  3. data/CONTRIBUTING.md +136 -0
  4. data/{COPYING → MIT-LICENSE} +4 -2
  5. data/README.rdoc +355 -0
  6. data/Rakefile +64 -98
  7. data/SPEC.rdoc +292 -0
  8. data/bin/rackup +3 -174
  9. data/contrib/rack.png +0 -0
  10. data/contrib/rack.svg +150 -0
  11. data/contrib/rack_logo.svg +164 -111
  12. data/contrib/rdoc.css +412 -0
  13. data/example/lobster.ru +2 -0
  14. data/example/protectedlobster.rb +4 -2
  15. data/example/protectedlobster.ru +3 -1
  16. data/lib/rack/auth/abstract/handler.rb +7 -5
  17. data/lib/rack/auth/abstract/request.rb +12 -2
  18. data/lib/rack/auth/basic.rb +6 -4
  19. data/lib/rack/auth/digest/md5.rb +20 -13
  20. data/lib/rack/auth/digest/nonce.rb +6 -4
  21. data/lib/rack/auth/digest/params.rb +11 -12
  22. data/lib/rack/auth/digest/request.rb +15 -12
  23. data/lib/rack/body_proxy.rb +45 -0
  24. data/lib/rack/builder.rb +213 -19
  25. data/lib/rack/cascade.rb +50 -18
  26. data/lib/rack/chunked.rb +95 -27
  27. data/lib/rack/common_logger.rb +84 -0
  28. data/lib/rack/conditional_get.rb +83 -0
  29. data/lib/rack/config.rb +22 -0
  30. data/lib/rack/content_length.rb +19 -10
  31. data/lib/rack/content_type.rb +12 -5
  32. data/lib/rack/core_ext/regexp.rb +14 -0
  33. data/lib/rack/deflater.rb +90 -42
  34. data/lib/rack/directory.rb +118 -72
  35. data/lib/rack/etag.rb +77 -0
  36. data/lib/rack/events.rb +153 -0
  37. data/lib/rack/file.rb +4 -85
  38. data/lib/rack/files.rb +218 -0
  39. data/lib/rack/handler/cgi.rb +22 -24
  40. data/lib/rack/handler/fastcgi.rb +34 -24
  41. data/lib/rack/handler/lsws.rb +16 -15
  42. data/lib/rack/handler/scgi.rb +38 -29
  43. data/lib/rack/handler/thin.rb +23 -7
  44. data/lib/rack/handler/webrick.rb +95 -37
  45. data/lib/rack/handler.rb +49 -14
  46. data/lib/rack/head.rb +19 -13
  47. data/lib/rack/lint.rb +466 -217
  48. data/lib/rack/lobster.rb +19 -14
  49. data/lib/rack/lock.rb +24 -8
  50. data/lib/rack/logger.rb +20 -0
  51. data/lib/rack/media_type.rb +53 -0
  52. data/lib/rack/method_override.rb +52 -0
  53. data/lib/rack/mime.rb +652 -171
  54. data/lib/rack/mock.rb +203 -64
  55. data/lib/rack/multipart/generator.rb +97 -0
  56. data/lib/rack/multipart/parser.rb +440 -0
  57. data/lib/rack/multipart/uploaded_file.rb +41 -0
  58. data/lib/rack/multipart.rb +64 -0
  59. data/lib/rack/null_logger.rb +39 -0
  60. data/lib/rack/query_parser.rb +266 -0
  61. data/lib/rack/recursive.rb +18 -11
  62. data/lib/rack/reloader.rb +13 -5
  63. data/lib/rack/request.rb +607 -191
  64. data/lib/rack/response.rb +245 -110
  65. data/lib/rack/rewindable_input.rb +15 -21
  66. data/lib/rack/runtime.rb +34 -0
  67. data/lib/rack/sendfile.rb +192 -0
  68. data/lib/rack/server.rb +466 -0
  69. data/lib/rack/session/abstract/id.rb +449 -68
  70. data/lib/rack/session/cookie.rb +159 -47
  71. data/lib/rack/session/memcache.rb +4 -103
  72. data/lib/rack/session/pool.rb +39 -49
  73. data/lib/rack/show_exceptions.rb +390 -0
  74. data/lib/rack/{showstatus.rb → show_status.rb} +21 -14
  75. data/lib/rack/static.rb +164 -14
  76. data/lib/rack/tempfile_reaper.rb +22 -0
  77. data/lib/rack/urlmap.rb +60 -18
  78. data/lib/rack/utils.rb +508 -277
  79. data/lib/rack/version.rb +29 -0
  80. data/lib/rack.rb +85 -34
  81. data/rack.gemspec +43 -51
  82. metadata +119 -207
  83. data/KNOWN-ISSUES +0 -18
  84. data/RDOX +0 -428
  85. data/README +0 -364
  86. data/SPEC +0 -164
  87. data/lib/rack/adapter/camping.rb +0 -22
  88. data/lib/rack/auth/openid.rb +0 -480
  89. data/lib/rack/commonlogger.rb +0 -61
  90. data/lib/rack/conditionalget.rb +0 -47
  91. data/lib/rack/handler/evented_mongrel.rb +0 -8
  92. data/lib/rack/handler/mongrel.rb +0 -87
  93. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  94. data/lib/rack/methodoverride.rb +0 -27
  95. data/lib/rack/showexceptions.rb +0 -349
  96. data/test/cgi/lighttpd.conf +0 -20
  97. data/test/cgi/test +0 -9
  98. data/test/cgi/test.fcgi +0 -8
  99. data/test/cgi/test.ru +0 -7
  100. data/test/multipart/binary +0 -0
  101. data/test/multipart/empty +0 -10
  102. data/test/multipart/ie +0 -6
  103. data/test/multipart/nested +0 -10
  104. data/test/multipart/none +0 -9
  105. data/test/multipart/semicolon +0 -6
  106. data/test/multipart/text +0 -10
  107. data/test/spec_rack_auth_basic.rb +0 -73
  108. data/test/spec_rack_auth_digest.rb +0 -226
  109. data/test/spec_rack_auth_openid.rb +0 -84
  110. data/test/spec_rack_builder.rb +0 -84
  111. data/test/spec_rack_camping.rb +0 -51
  112. data/test/spec_rack_cascade.rb +0 -50
  113. data/test/spec_rack_cgi.rb +0 -89
  114. data/test/spec_rack_chunked.rb +0 -62
  115. data/test/spec_rack_commonlogger.rb +0 -32
  116. data/test/spec_rack_conditionalget.rb +0 -41
  117. data/test/spec_rack_content_length.rb +0 -43
  118. data/test/spec_rack_content_type.rb +0 -30
  119. data/test/spec_rack_deflater.rb +0 -127
  120. data/test/spec_rack_directory.rb +0 -61
  121. data/test/spec_rack_fastcgi.rb +0 -89
  122. data/test/spec_rack_file.rb +0 -75
  123. data/test/spec_rack_handler.rb +0 -43
  124. data/test/spec_rack_head.rb +0 -30
  125. data/test/spec_rack_lint.rb +0 -521
  126. data/test/spec_rack_lobster.rb +0 -45
  127. data/test/spec_rack_lock.rb +0 -38
  128. data/test/spec_rack_methodoverride.rb +0 -60
  129. data/test/spec_rack_mock.rb +0 -157
  130. data/test/spec_rack_mongrel.rb +0 -189
  131. data/test/spec_rack_recursive.rb +0 -77
  132. data/test/spec_rack_request.rb +0 -504
  133. data/test/spec_rack_response.rb +0 -218
  134. data/test/spec_rack_rewindable_input.rb +0 -118
  135. data/test/spec_rack_session_cookie.rb +0 -82
  136. data/test/spec_rack_session_memcache.rb +0 -240
  137. data/test/spec_rack_session_pool.rb +0 -172
  138. data/test/spec_rack_showexceptions.rb +0 -21
  139. data/test/spec_rack_showstatus.rb +0 -72
  140. data/test/spec_rack_static.rb +0 -37
  141. data/test/spec_rack_thin.rb +0 -91
  142. data/test/spec_rack_urlmap.rb +0 -185
  143. data/test/spec_rack_utils.rb +0 -387
  144. data/test/spec_rack_webrick.rb +0 -130
  145. data/test/testrequest.rb +0 -57
  146. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  147. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/lib/rack/lobster.rb CHANGED
@@ -1,7 +1,6 @@
1
- require 'zlib'
1
+ # frozen_string_literal: true
2
2
 
3
- require 'rack/request'
4
- require 'rack/response'
3
+ require 'zlib'
5
4
 
6
5
  module Rack
7
6
  # Paste has a Pony, Rack has a Lobster!
@@ -12,7 +11,7 @@ module Rack
12
11
  I8jyiTlhTcYXkekJAzTyYN6E08A+dk8voBkAVTJQ==".delete("\n ").unpack("m*")[0])
13
12
 
14
13
  LambdaLobster = lambda { |env|
15
- if env["QUERY_STRING"].include?("flip")
14
+ if env[QUERY_STRING].include?("flip")
16
15
  lobster = LobsterString.split("\n").
17
16
  map { |line| line.ljust(42).reverse }.
18
17
  join("\n")
@@ -25,16 +24,21 @@ module Rack
25
24
  content = ["<title>Lobstericious!</title>",
26
25
  "<pre>", lobster, "</pre>",
27
26
  "<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]
27
+ length = content.inject(0) { |a, e| a + e.size }.to_s
28
+ [200, { CONTENT_TYPE => "text/html", CONTENT_LENGTH => length }, content]
30
29
  }
31
30
 
32
31
  def call(env)
33
32
  req = Request.new(env)
34
33
  if req.GET["flip"] == "left"
35
- lobster = LobsterString.split("\n").
36
- map { |line| line.ljust(42).reverse }.
37
- join("\n")
34
+ lobster = LobsterString.split("\n").map do |line|
35
+ line.ljust(42).reverse.
36
+ gsub('\\', 'TEMP').
37
+ gsub('/', '\\').
38
+ gsub('TEMP', '/').
39
+ gsub('{', '}').
40
+ gsub('(', ')')
41
+ end.join("\n")
38
42
  href = "?flip=right"
39
43
  elsif req.GET["flip"] == "crash"
40
44
  raise "Lobster crashed"
@@ -57,9 +61,10 @@ module Rack
57
61
  end
58
62
 
59
63
  if $0 == __FILE__
60
- require 'rack'
61
- require 'rack/showexceptions'
62
- Rack::Handler::WEBrick.run \
63
- Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)),
64
- :Port => 9292
64
+ # :nocov:
65
+ require_relative '../rack'
66
+ Rack::Server.start(
67
+ app: Rack::ShowExceptions.new(Rack::Lint.new(Rack::Lobster.new)), Port: 9292
68
+ )
69
+ # :nocov:
65
70
  end
data/lib/rack/lock.rb CHANGED
@@ -1,16 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thread'
4
+
1
5
  module Rack
6
+ # Rack::Lock locks every request inside a mutex, so that every request
7
+ # will effectively be executed synchronously.
2
8
  class Lock
3
- FLAG = 'rack.multithread'.freeze
4
-
5
- def initialize(app, lock = Mutex.new)
6
- @app, @lock = app, lock
9
+ def initialize(app, mutex = Mutex.new)
10
+ @app, @mutex = app, mutex
7
11
  end
8
12
 
9
13
  def call(env)
10
- old, env[FLAG] = env[FLAG], false
11
- @lock.synchronize { @app.call(env) }
12
- ensure
13
- env[FLAG] = old
14
+ @mutex.lock
15
+ @env = env
16
+ @old_rack_multithread = env[RACK_MULTITHREAD]
17
+ begin
18
+ response = @app.call(env.merge!(RACK_MULTITHREAD => false))
19
+ returned = response << BodyProxy.new(response.pop) { unlock }
20
+ ensure
21
+ unlock unless returned
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def unlock
28
+ @mutex.unlock
29
+ @env[RACK_MULTITHREAD] = @old_rack_multithread
14
30
  end
15
31
  end
16
32
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module Rack
6
+ # Sets up rack.logger to write to rack.errors stream
7
+ class Logger
8
+ def initialize(app, level = ::Logger::INFO)
9
+ @app, @level = app, level
10
+ end
11
+
12
+ def call(env)
13
+ logger = ::Logger.new(env[RACK_ERRORS])
14
+ logger.level = @level
15
+
16
+ env[RACK_LOGGER] = logger
17
+ @app.call(env)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,53 @@
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 = /[;,]/
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
+ if type = content_type.split(SPLIT_PATTERN, 2).first
19
+ type.rstrip!
20
+ type.downcase!
21
+ type
22
+ end
23
+ end
24
+
25
+ # The media type parameters provided in CONTENT_TYPE as a Hash, or
26
+ # an empty Hash if no CONTENT_TYPE or media-type parameters were
27
+ # provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8",
28
+ # this method responds with the following Hash:
29
+ # { 'charset' => 'utf-8' }
30
+ #
31
+ # This will pass back parameters with empty strings in the hash if they
32
+ # lack a value (e.g., "text/plain;charset=" will return { 'charset' => '' },
33
+ # and "text/plain;charset" will return { 'charset' => '' }, similarly to
34
+ # the query params parser (barring the latter case, which returns nil instead)).
35
+ def params(content_type)
36
+ return {} if content_type.nil?
37
+
38
+ content_type.split(SPLIT_PATTERN)[1..-1].each_with_object({}) do |s, hsh|
39
+ s.strip!
40
+ k, v = s.split('=', 2)
41
+ k.downcase!
42
+ hsh[k] = strip_doublequotes(v)
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def strip_doublequotes(str)
49
+ (str && str.start_with?('"') && str.end_with?('"')) ? str[1..-2] : str || ''
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class MethodOverride
5
+ HTTP_METHODS = %w[GET HEAD PUT POST DELETE OPTIONS PATCH LINK UNLINK]
6
+
7
+ METHOD_OVERRIDE_PARAM_KEY = "_method"
8
+ HTTP_METHOD_OVERRIDE_HEADER = "HTTP_X_HTTP_METHOD_OVERRIDE"
9
+ ALLOWED_METHODS = %w[POST]
10
+
11
+ def initialize(app)
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+ if allowed_methods.include?(env[REQUEST_METHOD])
17
+ method = method_override(env)
18
+ if HTTP_METHODS.include?(method)
19
+ env[RACK_METHODOVERRIDE_ORIGINAL_METHOD] = env[REQUEST_METHOD]
20
+ env[REQUEST_METHOD] = method
21
+ end
22
+ end
23
+
24
+ @app.call(env)
25
+ end
26
+
27
+ def method_override(env)
28
+ req = Request.new(env)
29
+ method = method_override_param(req) ||
30
+ env[HTTP_METHOD_OVERRIDE_HEADER]
31
+ begin
32
+ method.to_s.upcase
33
+ rescue ArgumentError
34
+ env[RACK_ERRORS].puts "Invalid string for method"
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def allowed_methods
41
+ ALLOWED_METHODS
42
+ end
43
+
44
+ def method_override_param(req)
45
+ req.POST[METHOD_OVERRIDE_PARAM_KEY]
46
+ rescue Utils::InvalidParameterError, Utils::ParameterTypeError, QueryParser::ParamsTooDeepError
47
+ req.get_header(RACK_ERRORS).puts "Invalid or incomplete POST params"
48
+ rescue EOFError
49
+ req.get_header(RACK_ERRORS).puts "Bad request content body"
50
+ end
51
+ end
52
+ end