rack 2.0.1 → 2.2.17

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 (189) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +795 -0
  3. data/CONTRIBUTING.md +136 -0
  4. data/{COPYING → MIT-LICENSE} +4 -2
  5. data/README.rdoc +188 -145
  6. data/Rakefile +37 -23
  7. data/{SPEC → SPEC.rdoc} +46 -17
  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 +6 -4
  15. data/lib/rack/auth/digest/md5.rb +13 -11
  16. data/lib/rack/auth/digest/nonce.rb +5 -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 +37 -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 +60 -70
  30. data/lib/rack/directory.rb +84 -64
  31. data/lib/rack/etag.rb +8 -5
  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 +19 -10
  41. data/lib/rack/handler.rb +7 -2
  42. data/lib/rack/head.rb +1 -1
  43. data/lib/rack/lint.rb +221 -186
  44. data/lib/rack/lobster.rb +10 -10
  45. data/lib/rack/lock.rb +14 -4
  46. data/lib/rack/logger.rb +2 -0
  47. data/lib/rack/media_type.rb +23 -8
  48. data/lib/rack/method_override.rb +13 -4
  49. data/lib/rack/mime.rb +9 -1
  50. data/lib/rack/mock.rb +135 -29
  51. data/lib/rack/multipart/generator.rb +17 -13
  52. data/lib/rack/multipart/parser.rb +85 -68
  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 +108 -36
  57. data/lib/rack/recursive.rb +7 -5
  58. data/lib/rack/reloader.rb +8 -4
  59. data/lib/rack/request.rb +232 -60
  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 +14 -10
  64. data/lib/rack/server.rb +97 -25
  65. data/lib/rack/session/abstract/id.rb +113 -25
  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 +24 -10
  69. data/lib/rack/show_exceptions.rb +22 -18
  70. data/lib/rack/show_status.rb +9 -9
  71. data/lib/rack/static.rb +25 -12
  72. data/lib/rack/tempfile_reaper.rb +1 -1
  73. data/lib/rack/urlmap.rb +13 -7
  74. data/lib/rack/utils.rb +135 -123
  75. data/lib/rack/version.rb +29 -0
  76. data/lib/rack.rb +67 -73
  77. data/rack.gemspec +40 -29
  78. metadata +25 -184
  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_percent_escaped_quotes +0 -6
  114. data/test/multipart/filename_with_single_quote +0 -7
  115. data/test/multipart/filename_with_unescaped_percentages +0 -6
  116. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  117. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  118. data/test/multipart/filename_with_unescaped_quotes +0 -6
  119. data/test/multipart/ie +0 -6
  120. data/test/multipart/invalid_character +0 -6
  121. data/test/multipart/mixed_files +0 -21
  122. data/test/multipart/nested +0 -10
  123. data/test/multipart/none +0 -9
  124. data/test/multipart/quoted +0 -15
  125. data/test/multipart/rack-logo.png +0 -0
  126. data/test/multipart/semicolon +0 -6
  127. data/test/multipart/text +0 -15
  128. data/test/multipart/three_files_three_fields +0 -31
  129. data/test/multipart/unity3d_wwwform +0 -11
  130. data/test/multipart/webkit +0 -32
  131. data/test/rackup/config.ru +0 -31
  132. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  133. data/test/spec_auth_basic.rb +0 -89
  134. data/test/spec_auth_digest.rb +0 -260
  135. data/test/spec_body_proxy.rb +0 -85
  136. data/test/spec_builder.rb +0 -233
  137. data/test/spec_cascade.rb +0 -63
  138. data/test/spec_cgi.rb +0 -84
  139. data/test/spec_chunked.rb +0 -103
  140. data/test/spec_common_logger.rb +0 -95
  141. data/test/spec_conditional_get.rb +0 -103
  142. data/test/spec_config.rb +0 -23
  143. data/test/spec_content_length.rb +0 -86
  144. data/test/spec_content_type.rb +0 -46
  145. data/test/spec_deflater.rb +0 -365
  146. data/test/spec_directory.rb +0 -148
  147. data/test/spec_etag.rb +0 -108
  148. data/test/spec_events.rb +0 -133
  149. data/test/spec_fastcgi.rb +0 -85
  150. data/test/spec_file.rb +0 -251
  151. data/test/spec_handler.rb +0 -57
  152. data/test/spec_head.rb +0 -46
  153. data/test/spec_lint.rb +0 -515
  154. data/test/spec_lobster.rb +0 -59
  155. data/test/spec_lock.rb +0 -194
  156. data/test/spec_logger.rb +0 -24
  157. data/test/spec_media_type.rb +0 -42
  158. data/test/spec_method_override.rb +0 -83
  159. data/test/spec_mime.rb +0 -51
  160. data/test/spec_mock.rb +0 -342
  161. data/test/spec_multipart.rb +0 -716
  162. data/test/spec_null_logger.rb +0 -21
  163. data/test/spec_recursive.rb +0 -75
  164. data/test/spec_request.rb +0 -1393
  165. data/test/spec_response.rb +0 -510
  166. data/test/spec_rewindable_input.rb +0 -128
  167. data/test/spec_runtime.rb +0 -50
  168. data/test/spec_sendfile.rb +0 -125
  169. data/test/spec_server.rb +0 -193
  170. data/test/spec_session_abstract_id.rb +0 -31
  171. data/test/spec_session_abstract_session_hash.rb +0 -28
  172. data/test/spec_session_cookie.rb +0 -442
  173. data/test/spec_session_memcache.rb +0 -320
  174. data/test/spec_session_pool.rb +0 -210
  175. data/test/spec_show_exceptions.rb +0 -80
  176. data/test/spec_show_status.rb +0 -104
  177. data/test/spec_static.rb +0 -184
  178. data/test/spec_tempfile_reaper.rb +0 -64
  179. data/test/spec_thin.rb +0 -96
  180. data/test/spec_urlmap.rb +0 -237
  181. data/test/spec_utils.rb +0 -742
  182. data/test/spec_version.rb +0 -11
  183. data/test/spec_webrick.rb +0 -208
  184. data/test/static/another/index.html +0 -1
  185. data/test/static/foo.html +0 -1
  186. data/test/static/index.html +0 -1
  187. data/test/testrequest.rb +0 -78
  188. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  189. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/test/spec_version.rb DELETED
@@ -1,11 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- require 'minitest/autorun'
3
- require 'rack'
4
-
5
- describe Rack do
6
- describe 'version' do
7
- it 'defaults to a hard-coded api version' do
8
- Rack.version.must_equal "1.3"
9
- end
10
- end
11
- end
data/test/spec_webrick.rb DELETED
@@ -1,208 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/mock'
3
- require 'concurrent/atomic/count_down_latch'
4
- require File.expand_path('../testrequest', __FILE__)
5
-
6
- Thread.abort_on_exception = true
7
-
8
- describe Rack::Handler::WEBrick do
9
- include TestRequest::Helpers
10
-
11
- before do
12
- @server = WEBrick::HTTPServer.new(:Host => @host='127.0.0.1',
13
- :Port => @port=9202,
14
- :Logger => WEBrick::Log.new(nil, WEBrick::BasicLog::WARN),
15
- :AccessLog => [])
16
- @server.mount "/test", Rack::Handler::WEBrick,
17
- Rack::Lint.new(TestRequest.new)
18
- @thread = Thread.new { @server.start }
19
- trap(:INT) { @server.shutdown }
20
- @status_thread = Thread.new do
21
- seconds = 10
22
- wait_time = 0.1
23
- until is_running? || seconds <= 0
24
- seconds -= wait_time
25
- sleep wait_time
26
- end
27
- raise "Server never reached status 'Running'" unless is_running?
28
- end
29
- end
30
-
31
- def is_running?
32
- @server.status == :Running
33
- end
34
-
35
- it "respond" do
36
- GET("/test")
37
- status.must_equal 200
38
- end
39
-
40
- it "be a WEBrick" do
41
- GET("/test")
42
- status.must_equal 200
43
- response["SERVER_SOFTWARE"].must_match(/WEBrick/)
44
- response["HTTP_VERSION"].must_equal "HTTP/1.1"
45
- response["SERVER_PROTOCOL"].must_equal "HTTP/1.1"
46
- response["SERVER_PORT"].must_equal "9202"
47
- response["SERVER_NAME"].must_equal "127.0.0.1"
48
- end
49
-
50
- it "have rack headers" do
51
- GET("/test")
52
- response["rack.version"].must_equal [1,3]
53
- response["rack.multithread"].must_equal true
54
- assert_equal false, response["rack.multiprocess"]
55
- assert_equal false, response["rack.run_once"]
56
- end
57
-
58
- it "have CGI headers on GET" do
59
- GET("/test")
60
- response["REQUEST_METHOD"].must_equal "GET"
61
- response["SCRIPT_NAME"].must_equal "/test"
62
- response["REQUEST_PATH"].must_equal "/test"
63
- response["PATH_INFO"].must_equal ""
64
- response["QUERY_STRING"].must_equal ""
65
- response["test.postdata"].must_equal ""
66
-
67
- GET("/test/foo?quux=1")
68
- response["REQUEST_METHOD"].must_equal "GET"
69
- response["SCRIPT_NAME"].must_equal "/test"
70
- response["REQUEST_PATH"].must_equal "/test/foo"
71
- response["PATH_INFO"].must_equal "/foo"
72
- response["QUERY_STRING"].must_equal "quux=1"
73
-
74
- GET("/test/foo%25encoding?quux=1")
75
- response["REQUEST_METHOD"].must_equal "GET"
76
- response["SCRIPT_NAME"].must_equal "/test"
77
- response["REQUEST_PATH"].must_equal "/test/foo%25encoding"
78
- response["PATH_INFO"].must_equal "/foo%25encoding"
79
- response["QUERY_STRING"].must_equal "quux=1"
80
- end
81
-
82
- it "have CGI headers on POST" do
83
- POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
84
- status.must_equal 200
85
- response["REQUEST_METHOD"].must_equal "POST"
86
- response["SCRIPT_NAME"].must_equal "/test"
87
- response["REQUEST_PATH"].must_equal "/test"
88
- response["PATH_INFO"].must_equal ""
89
- response["QUERY_STRING"].must_equal ""
90
- response["HTTP_X_TEST_HEADER"].must_equal "42"
91
- response["test.postdata"].must_equal "rack-form-data=23"
92
- end
93
-
94
- it "support HTTP auth" do
95
- GET("/test", {:user => "ruth", :passwd => "secret"})
96
- response["HTTP_AUTHORIZATION"].must_equal "Basic cnV0aDpzZWNyZXQ="
97
- end
98
-
99
- it "set status" do
100
- GET("/test?secret")
101
- status.must_equal 403
102
- response["rack.url_scheme"].must_equal "http"
103
- end
104
-
105
- it "correctly set cookies" do
106
- @server.mount "/cookie-test", Rack::Handler::WEBrick,
107
- Rack::Lint.new(lambda { |req|
108
- res = Rack::Response.new
109
- res.set_cookie "one", "1"
110
- res.set_cookie "two", "2"
111
- res.finish
112
- })
113
-
114
- Net::HTTP.start(@host, @port) { |http|
115
- res = http.get("/cookie-test")
116
- res.code.to_i.must_equal 200
117
- res.get_fields("set-cookie").must_equal ["one=1", "two=2"]
118
- }
119
- end
120
-
121
- it "provide a .run" do
122
- block_ran = false
123
- latch = Concurrent::CountDownLatch.new 1
124
-
125
- t = Thread.new do
126
- Rack::Handler::WEBrick.run(lambda {},
127
- {
128
- :Host => '127.0.0.1',
129
- :Port => 9210,
130
- :Logger => WEBrick::Log.new(nil, WEBrick::BasicLog::WARN),
131
- :AccessLog => []}) { |server|
132
- block_ran = true
133
- assert_kind_of WEBrick::HTTPServer, server
134
- @s = server
135
- latch.count_down
136
- }
137
- end
138
-
139
- latch.wait
140
- @s.shutdown
141
- t.join
142
- end
143
-
144
- it "return repeated headers" do
145
- @server.mount "/headers", Rack::Handler::WEBrick,
146
- Rack::Lint.new(lambda { |req|
147
- [
148
- 401,
149
- { "Content-Type" => "text/plain",
150
- "WWW-Authenticate" => "Bar realm=X\nBaz realm=Y" },
151
- [""]
152
- ]
153
- })
154
-
155
- Net::HTTP.start(@host, @port) { |http|
156
- res = http.get("/headers")
157
- res.code.to_i.must_equal 401
158
- res["www-authenticate"].must_equal "Bar realm=X, Baz realm=Y"
159
- }
160
- end
161
-
162
- it "support Rack partial hijack" do
163
- io_lambda = lambda{ |io|
164
- 5.times do
165
- io.write "David\r\n"
166
- end
167
- io.close
168
- }
169
-
170
- @server.mount "/partial", Rack::Handler::WEBrick,
171
- Rack::Lint.new(lambda{ |req|
172
- [
173
- 200,
174
- {"rack.hijack" => io_lambda},
175
- [""]
176
- ]
177
- })
178
-
179
- Net::HTTP.start(@host, @port){ |http|
180
- res = http.get("/partial")
181
- res.body.must_equal "David\r\nDavid\r\nDavid\r\nDavid\r\nDavid\r\n"
182
- }
183
- end
184
-
185
- it "produce correct HTTP semantics with and without app chunking" do
186
- @server.mount "/chunked", Rack::Handler::WEBrick,
187
- Rack::Lint.new(lambda{ |req|
188
- [
189
- 200,
190
- {"Transfer-Encoding" => "chunked"},
191
- ["7\r\nchunked\r\n0\r\n\r\n"]
192
- ]
193
- })
194
-
195
- Net::HTTP.start(@host, @port){ |http|
196
- res = http.get("/chunked")
197
- res["Transfer-Encoding"].must_equal "chunked"
198
- res["Content-Length"].must_equal nil
199
- res.body.must_equal "chunked"
200
- }
201
- end
202
-
203
- after do
204
- @status_thread.join
205
- @server.shutdown
206
- @thread.join
207
- end
208
- end
@@ -1 +0,0 @@
1
- another index!
data/test/static/foo.html DELETED
@@ -1 +0,0 @@
1
- foo.html!
@@ -1 +0,0 @@
1
- index!
data/test/testrequest.rb DELETED
@@ -1,78 +0,0 @@
1
- require 'yaml'
2
- require 'net/http'
3
- require 'rack/lint'
4
-
5
- class TestRequest
6
- NOSERIALIZE = [Method, Proc, Rack::Lint::InputWrapper]
7
-
8
- def call(env)
9
- status = env["QUERY_STRING"] =~ /secret/ ? 403 : 200
10
- env["test.postdata"] = env["rack.input"].read
11
- minienv = env.dup
12
- # This may in the future want to replace with a dummy value instead.
13
- minienv.delete_if { |k,v| NOSERIALIZE.any? { |c| v.kind_of?(c) } }
14
- body = minienv.to_yaml
15
- size = body.bytesize
16
- [status, {"Content-Type" => "text/yaml", "Content-Length" => size.to_s}, [body]]
17
- end
18
-
19
- module Helpers
20
- attr_reader :status, :response
21
-
22
- ROOT = File.expand_path(File.dirname(__FILE__) + "/..")
23
- ENV["RUBYOPT"] = "-I#{ROOT}/lib -rubygems"
24
-
25
- def root
26
- ROOT
27
- end
28
-
29
- def rackup
30
- "#{ROOT}/bin/rackup"
31
- end
32
-
33
- def GET(path, header={})
34
- Net::HTTP.start(@host, @port) { |http|
35
- user = header.delete(:user)
36
- passwd = header.delete(:passwd)
37
-
38
- get = Net::HTTP::Get.new(path, header)
39
- get.basic_auth user, passwd if user && passwd
40
- http.request(get) { |response|
41
- @status = response.code.to_i
42
- begin
43
- @response = YAML.load(response.body)
44
- rescue TypeError, ArgumentError
45
- @response = nil
46
- end
47
- }
48
- }
49
- end
50
-
51
- def POST(path, formdata={}, header={})
52
- Net::HTTP.start(@host, @port) { |http|
53
- user = header.delete(:user)
54
- passwd = header.delete(:passwd)
55
-
56
- post = Net::HTTP::Post.new(path, header)
57
- post.form_data = formdata
58
- post.basic_auth user, passwd if user && passwd
59
- http.request(post) { |response|
60
- @status = response.code.to_i
61
- @response = YAML.load(response.body)
62
- }
63
- }
64
- end
65
- end
66
- end
67
-
68
- class StreamingRequest
69
- def self.call(env)
70
- [200, {"Content-Type" => "text/plain"}, new]
71
- end
72
-
73
- def each
74
- yield "hello there!\n"
75
- sleep 5
76
- yield "that is all.\n"
77
- end
78
- end
@@ -1,7 +0,0 @@
1
- module Rack
2
- module Handler
3
- # this class doesn't do anything, we're just seeing if we get it.
4
- class Unregistered
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- module Rack
2
- module Handler
3
- # this class doesn't do anything, we're just seeing if we get it.
4
- class UnregisteredLongOne
5
- end
6
- end
7
- end