rack 2.0.9.4 → 2.1.0

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 (188) hide show
  1. checksums.yaml +4 -4
  2. data/{HISTORY.md → CHANGELOG.md} +214 -164
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +79 -133
  5. data/Rakefile +25 -18
  6. data/SPEC +9 -9
  7. data/bin/rackup +1 -0
  8. data/example/lobster.ru +2 -0
  9. data/example/protectedlobster.rb +3 -1
  10. data/example/protectedlobster.ru +2 -0
  11. data/lib/rack/auth/abstract/handler.rb +3 -1
  12. data/lib/rack/auth/abstract/request.rb +2 -0
  13. data/lib/rack/auth/basic.rb +4 -1
  14. data/lib/rack/auth/digest/md5.rb +9 -7
  15. data/lib/rack/auth/digest/nonce.rb +6 -3
  16. data/lib/rack/auth/digest/params.rb +4 -2
  17. data/lib/rack/auth/digest/request.rb +2 -0
  18. data/lib/rack/body_proxy.rb +3 -6
  19. data/lib/rack/builder.rb +38 -15
  20. data/lib/rack/cascade.rb +6 -5
  21. data/lib/rack/chunked.rb +29 -6
  22. data/lib/rack/common_logger.rb +9 -11
  23. data/lib/rack/conditional_get.rb +3 -1
  24. data/lib/rack/config.rb +2 -0
  25. data/lib/rack/content_length.rb +3 -1
  26. data/lib/rack/content_type.rb +3 -1
  27. data/lib/rack/core_ext/regexp.rb +14 -0
  28. data/lib/rack/deflater.rb +28 -17
  29. data/lib/rack/directory.rb +17 -14
  30. data/lib/rack/etag.rb +3 -1
  31. data/lib/rack/events.rb +5 -3
  32. data/lib/rack/file.rb +5 -173
  33. data/lib/rack/files.rb +178 -0
  34. data/lib/rack/handler/cgi.rb +3 -1
  35. data/lib/rack/handler/fastcgi.rb +4 -2
  36. data/lib/rack/handler/lsws.rb +3 -1
  37. data/lib/rack/handler/scgi.rb +9 -6
  38. data/lib/rack/handler/thin.rb +3 -1
  39. data/lib/rack/handler/webrick.rb +4 -2
  40. data/lib/rack/handler.rb +7 -2
  41. data/lib/rack/head.rb +2 -0
  42. data/lib/rack/lint.rb +15 -12
  43. data/lib/rack/lobster.rb +7 -5
  44. data/lib/rack/lock.rb +2 -0
  45. data/lib/rack/logger.rb +2 -0
  46. data/lib/rack/media_type.rb +10 -5
  47. data/lib/rack/method_override.rb +4 -2
  48. data/lib/rack/mime.rb +9 -1
  49. data/lib/rack/mock.rb +74 -15
  50. data/lib/rack/multipart/generator.rb +6 -7
  51. data/lib/rack/multipart/parser.rb +55 -62
  52. data/lib/rack/multipart/uploaded_file.rb +2 -0
  53. data/lib/rack/multipart.rb +6 -3
  54. data/lib/rack/null_logger.rb +2 -0
  55. data/lib/rack/query_parser.rb +51 -25
  56. data/lib/rack/recursive.rb +7 -5
  57. data/lib/rack/reloader.rb +10 -4
  58. data/lib/rack/request.rb +79 -26
  59. data/lib/rack/response.rb +71 -31
  60. data/lib/rack/rewindable_input.rb +4 -2
  61. data/lib/rack/runtime.rb +4 -2
  62. data/lib/rack/sendfile.rb +15 -8
  63. data/lib/rack/server.rb +88 -16
  64. data/lib/rack/session/abstract/id.rb +40 -22
  65. data/lib/rack/session/cookie.rb +10 -9
  66. data/lib/rack/session/memcache.rb +4 -93
  67. data/lib/rack/session/pool.rb +4 -2
  68. data/lib/rack/show_exceptions.rb +15 -9
  69. data/lib/rack/show_status.rb +4 -2
  70. data/lib/rack/static.rb +15 -10
  71. data/lib/rack/tempfile_reaper.rb +2 -0
  72. data/lib/rack/urlmap.rb +11 -2
  73. data/lib/rack/utils.rb +64 -93
  74. data/lib/rack.rb +63 -60
  75. data/rack.gemspec +17 -7
  76. metadata +33 -175
  77. data/test/builder/an_underscore_app.rb +0 -5
  78. data/test/builder/anything.rb +0 -5
  79. data/test/builder/comment.ru +0 -4
  80. data/test/builder/end.ru +0 -5
  81. data/test/builder/line.ru +0 -1
  82. data/test/builder/options.ru +0 -2
  83. data/test/cgi/assets/folder/test.js +0 -1
  84. data/test/cgi/assets/fonts/font.eot +0 -1
  85. data/test/cgi/assets/images/image.png +0 -1
  86. data/test/cgi/assets/index.html +0 -1
  87. data/test/cgi/assets/javascripts/app.js +0 -1
  88. data/test/cgi/assets/stylesheets/app.css +0 -1
  89. data/test/cgi/lighttpd.conf +0 -26
  90. data/test/cgi/rackup_stub.rb +0 -6
  91. data/test/cgi/sample_rackup.ru +0 -5
  92. data/test/cgi/test +0 -9
  93. data/test/cgi/test+directory/test+file +0 -1
  94. data/test/cgi/test.fcgi +0 -9
  95. data/test/cgi/test.gz +0 -0
  96. data/test/cgi/test.ru +0 -5
  97. data/test/gemloader.rb +0 -10
  98. data/test/helper.rb +0 -34
  99. data/test/multipart/bad_robots +0 -259
  100. data/test/multipart/binary +0 -0
  101. data/test/multipart/content_type_and_no_filename +0 -6
  102. data/test/multipart/empty +0 -10
  103. data/test/multipart/fail_16384_nofile +0 -814
  104. data/test/multipart/file1.txt +0 -1
  105. data/test/multipart/filename_and_modification_param +0 -7
  106. data/test/multipart/filename_and_no_name +0 -6
  107. data/test/multipart/filename_with_encoded_words +0 -7
  108. data/test/multipart/filename_with_escaped_quotes +0 -6
  109. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  110. data/test/multipart/filename_with_null_byte +0 -7
  111. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  112. data/test/multipart/filename_with_single_quote +0 -7
  113. data/test/multipart/filename_with_unescaped_percentages +0 -6
  114. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  115. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  116. data/test/multipart/filename_with_unescaped_quotes +0 -6
  117. data/test/multipart/ie +0 -6
  118. data/test/multipart/invalid_character +0 -6
  119. data/test/multipart/mixed_files +0 -21
  120. data/test/multipart/nested +0 -10
  121. data/test/multipart/none +0 -9
  122. data/test/multipart/quoted +0 -15
  123. data/test/multipart/rack-logo.png +0 -0
  124. data/test/multipart/semicolon +0 -6
  125. data/test/multipart/text +0 -15
  126. data/test/multipart/three_files_three_fields +0 -31
  127. data/test/multipart/unity3d_wwwform +0 -11
  128. data/test/multipart/webkit +0 -32
  129. data/test/rackup/config.ru +0 -31
  130. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  131. data/test/spec_auth_basic.rb +0 -89
  132. data/test/spec_auth_digest.rb +0 -260
  133. data/test/spec_body_proxy.rb +0 -85
  134. data/test/spec_builder.rb +0 -233
  135. data/test/spec_cascade.rb +0 -63
  136. data/test/spec_cgi.rb +0 -84
  137. data/test/spec_chunked.rb +0 -103
  138. data/test/spec_common_logger.rb +0 -107
  139. data/test/spec_conditional_get.rb +0 -103
  140. data/test/spec_config.rb +0 -23
  141. data/test/spec_content_length.rb +0 -86
  142. data/test/spec_content_type.rb +0 -46
  143. data/test/spec_deflater.rb +0 -375
  144. data/test/spec_directory.rb +0 -148
  145. data/test/spec_etag.rb +0 -108
  146. data/test/spec_events.rb +0 -133
  147. data/test/spec_fastcgi.rb +0 -85
  148. data/test/spec_file.rb +0 -264
  149. data/test/spec_handler.rb +0 -57
  150. data/test/spec_head.rb +0 -46
  151. data/test/spec_lint.rb +0 -520
  152. data/test/spec_lobster.rb +0 -59
  153. data/test/spec_lock.rb +0 -204
  154. data/test/spec_logger.rb +0 -24
  155. data/test/spec_media_type.rb +0 -42
  156. data/test/spec_method_override.rb +0 -110
  157. data/test/spec_mime.rb +0 -51
  158. data/test/spec_mock.rb +0 -359
  159. data/test/spec_multipart.rb +0 -721
  160. data/test/spec_null_logger.rb +0 -21
  161. data/test/spec_recursive.rb +0 -75
  162. data/test/spec_request.rb +0 -1423
  163. data/test/spec_response.rb +0 -528
  164. data/test/spec_rewindable_input.rb +0 -128
  165. data/test/spec_runtime.rb +0 -50
  166. data/test/spec_sendfile.rb +0 -125
  167. data/test/spec_server.rb +0 -193
  168. data/test/spec_session_abstract_id.rb +0 -31
  169. data/test/spec_session_abstract_session_hash.rb +0 -45
  170. data/test/spec_session_cookie.rb +0 -442
  171. data/test/spec_session_memcache.rb +0 -357
  172. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  173. data/test/spec_session_pool.rb +0 -247
  174. data/test/spec_show_exceptions.rb +0 -93
  175. data/test/spec_show_status.rb +0 -104
  176. data/test/spec_static.rb +0 -184
  177. data/test/spec_tempfile_reaper.rb +0 -64
  178. data/test/spec_thin.rb +0 -96
  179. data/test/spec_urlmap.rb +0 -237
  180. data/test/spec_utils.rb +0 -742
  181. data/test/spec_version.rb +0 -11
  182. data/test/spec_webrick.rb +0 -206
  183. data/test/static/another/index.html +0 -1
  184. data/test/static/foo.html +0 -1
  185. data/test/static/index.html +0 -1
  186. data/test/testrequest.rb +0 -78
  187. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  188. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -1,85 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/body_proxy'
3
- require 'stringio'
4
-
5
- describe Rack::BodyProxy do
6
- it 'call each on the wrapped body' do
7
- called = false
8
- proxy = Rack::BodyProxy.new(['foo']) { }
9
- proxy.each do |str|
10
- called = true
11
- str.must_equal 'foo'
12
- end
13
- called.must_equal true
14
- end
15
-
16
- it 'call close on the wrapped body' do
17
- body = StringIO.new
18
- proxy = Rack::BodyProxy.new(body) { }
19
- proxy.close
20
- body.must_be :closed?
21
- end
22
-
23
- it 'only call close on the wrapped body if it responds to close' do
24
- body = []
25
- proxy = Rack::BodyProxy.new(body) { }
26
- proxy.close.must_be_nil
27
- end
28
-
29
- it 'call the passed block on close' do
30
- called = false
31
- proxy = Rack::BodyProxy.new([]) { called = true }
32
- called.must_equal false
33
- proxy.close
34
- called.must_equal true
35
- end
36
-
37
- it 'call the passed block on close even if there is an exception' do
38
- object = Object.new
39
- def object.close() raise "No!" end
40
- called = false
41
-
42
- begin
43
- proxy = Rack::BodyProxy.new(object) { called = true }
44
- called.must_equal false
45
- proxy.close
46
- rescue RuntimeError => e
47
- end
48
-
49
- raise "Expected exception to have been raised" unless e
50
- called.must_equal true
51
- end
52
-
53
- it 'allow multiple arguments in respond_to?' do
54
- body = []
55
- proxy = Rack::BodyProxy.new(body) { }
56
- proxy.respond_to?(:foo, false).must_equal false
57
- end
58
-
59
- it 'not respond to :to_ary' do
60
- body = Object.new.tap { |o| def o.to_ary() end }
61
- body.respond_to?(:to_ary).must_equal true
62
-
63
- proxy = Rack::BodyProxy.new(body) { }
64
- proxy.respond_to?(:to_ary).must_equal false
65
- proxy.respond_to?("to_ary").must_equal false
66
- end
67
-
68
- it 'not close more than one time' do
69
- count = 0
70
- proxy = Rack::BodyProxy.new([]) { count += 1; raise "Block invoked more than 1 time!" if count > 1 }
71
- 2.times { proxy.close }
72
- count.must_equal 1
73
- end
74
-
75
- it 'be closed when the callback is triggered' do
76
- closed = false
77
- proxy = Rack::BodyProxy.new([]) { closed = proxy.closed? }
78
- proxy.close
79
- closed.must_equal true
80
- end
81
-
82
- it 'provide an #each method' do
83
- Rack::BodyProxy.method_defined?(:each).must_equal true
84
- end
85
- end
data/test/spec_builder.rb DELETED
@@ -1,233 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/builder'
3
- require 'rack/lint'
4
- require 'rack/mock'
5
- require 'rack/show_exceptions'
6
- require 'rack/urlmap'
7
-
8
- class NothingMiddleware
9
- def initialize(app)
10
- @app = app
11
- end
12
- def call(env)
13
- @@env = env
14
- response = @app.call(env)
15
- response
16
- end
17
- def self.env
18
- @@env
19
- end
20
- end
21
-
22
- describe Rack::Builder do
23
- def builder(&block)
24
- Rack::Lint.new Rack::Builder.new(&block)
25
- end
26
-
27
- def builder_to_app(&block)
28
- Rack::Lint.new Rack::Builder.new(&block).to_app
29
- end
30
-
31
- it "supports mapping" do
32
- app = builder_to_app do
33
- map '/' do |outer_env|
34
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] }
35
- end
36
- map '/sub' do
37
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] }
38
- end
39
- end
40
- Rack::MockRequest.new(app).get("/").body.to_s.must_equal 'root'
41
- Rack::MockRequest.new(app).get("/sub").body.to_s.must_equal 'sub'
42
- end
43
-
44
- it "doesn't dupe env even when mapping" do
45
- app = builder_to_app do
46
- use NothingMiddleware
47
- map '/' do |outer_env|
48
- run lambda { |inner_env|
49
- inner_env['new_key'] = 'new_value'
50
- [200, {"Content-Type" => "text/plain"}, ['root']]
51
- }
52
- end
53
- end
54
- Rack::MockRequest.new(app).get("/").body.to_s.must_equal 'root'
55
- NothingMiddleware.env['new_key'].must_equal 'new_value'
56
- end
57
-
58
- it "chains apps by default" do
59
- app = builder_to_app do
60
- use Rack::ShowExceptions
61
- run lambda { |env| raise "bzzzt" }
62
- end
63
-
64
- Rack::MockRequest.new(app).get("/").must_be :server_error?
65
- Rack::MockRequest.new(app).get("/").must_be :server_error?
66
- Rack::MockRequest.new(app).get("/").must_be :server_error?
67
- end
68
-
69
- it "has implicit #to_app" do
70
- app = builder do
71
- use Rack::ShowExceptions
72
- run lambda { |env| raise "bzzzt" }
73
- end
74
-
75
- Rack::MockRequest.new(app).get("/").must_be :server_error?
76
- Rack::MockRequest.new(app).get("/").must_be :server_error?
77
- Rack::MockRequest.new(app).get("/").must_be :server_error?
78
- end
79
-
80
- it "supports blocks on use" do
81
- app = builder do
82
- use Rack::ShowExceptions
83
- use Rack::Auth::Basic do |username, password|
84
- 'secret' == password
85
- end
86
-
87
- run lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hi Boss']] }
88
- end
89
-
90
- response = Rack::MockRequest.new(app).get("/")
91
- response.must_be :client_error?
92
- response.status.must_equal 401
93
-
94
- # with auth...
95
- response = Rack::MockRequest.new(app).get("/",
96
- 'HTTP_AUTHORIZATION' => 'Basic ' + ["joe:secret"].pack("m*"))
97
- response.status.must_equal 200
98
- response.body.to_s.must_equal 'Hi Boss'
99
- end
100
-
101
- it "has explicit #to_app" do
102
- app = builder do
103
- use Rack::ShowExceptions
104
- run lambda { |env| raise "bzzzt" }
105
- end
106
-
107
- Rack::MockRequest.new(app).get("/").must_be :server_error?
108
- Rack::MockRequest.new(app).get("/").must_be :server_error?
109
- Rack::MockRequest.new(app).get("/").must_be :server_error?
110
- end
111
-
112
- it "can mix map and run for endpoints" do
113
- app = builder do
114
- map '/sub' do
115
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] }
116
- end
117
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] }
118
- end
119
-
120
- Rack::MockRequest.new(app).get("/").body.to_s.must_equal 'root'
121
- Rack::MockRequest.new(app).get("/sub").body.to_s.must_equal 'sub'
122
- end
123
-
124
- it "accepts middleware-only map blocks" do
125
- app = builder do
126
- map('/foo') { use Rack::ShowExceptions }
127
- run lambda { |env| raise "bzzzt" }
128
- end
129
-
130
- proc { Rack::MockRequest.new(app).get("/") }.must_raise(RuntimeError)
131
- Rack::MockRequest.new(app).get("/foo").must_be :server_error?
132
- end
133
-
134
- it "yields the generated app to a block for warmup" do
135
- warmed_up_app = nil
136
-
137
- app = Rack::Builder.new do
138
- warmup { |a| warmed_up_app = a }
139
- run lambda { |env| [200, {}, []] }
140
- end.to_app
141
-
142
- warmed_up_app.must_equal app
143
- end
144
-
145
- it "initialize apps once" do
146
- app = builder do
147
- class AppClass
148
- def initialize
149
- @called = 0
150
- end
151
- def call(env)
152
- raise "bzzzt" if @called > 0
153
- @called += 1
154
- [200, {'Content-Type' => 'text/plain'}, ['OK']]
155
- end
156
- end
157
-
158
- use Rack::ShowExceptions
159
- run AppClass.new
160
- end
161
-
162
- Rack::MockRequest.new(app).get("/").status.must_equal 200
163
- Rack::MockRequest.new(app).get("/").must_be :server_error?
164
- end
165
-
166
- it "allows use after run" do
167
- app = builder do
168
- run lambda { |env| raise "bzzzt" }
169
- use Rack::ShowExceptions
170
- end
171
-
172
- Rack::MockRequest.new(app).get("/").must_be :server_error?
173
- Rack::MockRequest.new(app).get("/").must_be :server_error?
174
- Rack::MockRequest.new(app).get("/").must_be :server_error?
175
- end
176
-
177
- it 'complains about a missing run' do
178
- proc do
179
- Rack::Lint.new Rack::Builder.app { use Rack::ShowExceptions }
180
- end.must_raise(RuntimeError)
181
- end
182
-
183
- describe "parse_file" do
184
- def config_file(name)
185
- File.join(File.dirname(__FILE__), 'builder', name)
186
- end
187
-
188
- it "parses commented options" do
189
- app, options = Rack::Builder.parse_file config_file('options.ru')
190
- options[:debug].must_equal true
191
- options[:environment].must_equal 'test'
192
- options[:Port].must_equal '2929'
193
- Rack::MockRequest.new(app).get("/").body.to_s.must_equal 'OK'
194
- end
195
-
196
- it "removes __END__ before evaluating app" do
197
- app, _ = Rack::Builder.parse_file config_file('end.ru')
198
- Rack::MockRequest.new(app).get("/").body.to_s.must_equal 'OK'
199
- end
200
-
201
- it "supports multi-line comments" do
202
- proc, env = Rack::Builder.parse_file(config_file('comment.ru'))
203
- proc.must_be_kind_of Proc
204
- env.must_equal({})
205
- end
206
-
207
- it "requires anything not ending in .ru" do
208
- $: << File.dirname(__FILE__)
209
- app, * = Rack::Builder.parse_file 'builder/anything'
210
- Rack::MockRequest.new(app).get("/").body.to_s.must_equal 'OK'
211
- $:.pop
212
- end
213
-
214
- it 'requires an_underscore_app not ending in .ru' do
215
- $: << File.dirname(__FILE__)
216
- app, * = Rack::Builder.parse_file 'builder/an_underscore_app'
217
- Rack::MockRequest.new(app).get('/').body.to_s.must_equal 'OK'
218
- $:.pop
219
- end
220
-
221
- it "sets __LINE__ correctly" do
222
- app, _ = Rack::Builder.parse_file config_file('line.ru')
223
- Rack::MockRequest.new(app).get("/").body.to_s.must_equal '1'
224
- end
225
- end
226
-
227
- describe 'new_from_string' do
228
- it "builds a rack app from string" do
229
- app, = Rack::Builder.new_from_string "run lambda{|env| [200, {'Content-Type' => 'text/plane'}, ['OK']] }"
230
- Rack::MockRequest.new(app).get("/").body.to_s.must_equal 'OK'
231
- end
232
- end
233
- end
data/test/spec_cascade.rb DELETED
@@ -1,63 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack'
3
- require 'rack/cascade'
4
- require 'rack/file'
5
- require 'rack/lint'
6
- require 'rack/urlmap'
7
- require 'rack/mock'
8
-
9
- describe Rack::Cascade do
10
- def cascade(*args)
11
- Rack::Lint.new Rack::Cascade.new(*args)
12
- end
13
-
14
- docroot = File.expand_path(File.dirname(__FILE__))
15
- app1 = Rack::File.new(docroot)
16
-
17
- app2 = Rack::URLMap.new("/crash" => lambda { |env| raise "boom" })
18
-
19
- app3 = Rack::URLMap.new("/foo" => lambda { |env|
20
- [200, { "Content-Type" => "text/plain"}, [""]]})
21
-
22
- it "dispatch onward on 404 and 405 by default" do
23
- cascade = cascade([app1, app2, app3])
24
- Rack::MockRequest.new(cascade).get("/cgi/test").must_be :ok?
25
- Rack::MockRequest.new(cascade).get("/foo").must_be :ok?
26
- Rack::MockRequest.new(cascade).get("/toobad").must_be :not_found?
27
- Rack::MockRequest.new(cascade).get("/cgi/../..").must_be :client_error?
28
-
29
- # Put is not allowed by Rack::File so it'll 405.
30
- Rack::MockRequest.new(cascade).put("/foo").must_be :ok?
31
- end
32
-
33
- it "dispatch onward on whatever is passed" do
34
- cascade = cascade([app1, app2, app3], [404, 403])
35
- Rack::MockRequest.new(cascade).get("/cgi/../bla").must_be :not_found?
36
- end
37
-
38
- it "return 404 if empty" do
39
- Rack::MockRequest.new(cascade([])).get('/').must_be :not_found?
40
- end
41
-
42
- it "append new app" do
43
- cascade = Rack::Cascade.new([], [404, 403])
44
- Rack::MockRequest.new(cascade).get('/').must_be :not_found?
45
- cascade << app2
46
- Rack::MockRequest.new(cascade).get('/cgi/test').must_be :not_found?
47
- Rack::MockRequest.new(cascade).get('/cgi/../bla').must_be :not_found?
48
- cascade << app1
49
- Rack::MockRequest.new(cascade).get('/cgi/test').must_be :ok?
50
- Rack::MockRequest.new(cascade).get('/cgi/../..').must_be :client_error?
51
- Rack::MockRequest.new(cascade).get('/foo').must_be :not_found?
52
- cascade << app3
53
- Rack::MockRequest.new(cascade).get('/foo').must_be :ok?
54
- end
55
-
56
- it "close the body on cascade" do
57
- body = StringIO.new
58
- closer = lambda { |env| [404, {}, body] }
59
- cascade = Rack::Cascade.new([closer, app3], [404])
60
- Rack::MockRequest.new(cascade).get("/foo").must_be :ok?
61
- body.must_be :closed?
62
- end
63
- end
data/test/spec_cgi.rb DELETED
@@ -1,84 +0,0 @@
1
- require 'helper'
2
-
3
- if defined? LIGHTTPD_PID
4
-
5
- require File.expand_path('../testrequest', __FILE__)
6
- require 'rack/handler/cgi'
7
-
8
- describe Rack::Handler::CGI do
9
- include TestRequest::Helpers
10
-
11
- before do
12
- @host = '127.0.0.1'
13
- @port = 9203
14
- end
15
-
16
- if `which lighttpd` && !$?.success?
17
- raise "lighttpd not found"
18
- end
19
-
20
- it "respond" do
21
- sleep 1
22
- GET("/test")
23
- response.wont_be :nil?
24
- end
25
-
26
- it "be a lighttpd" do
27
- GET("/test")
28
- status.must_equal 200
29
- response["SERVER_SOFTWARE"].must_match(/lighttpd/)
30
- response["HTTP_VERSION"].must_equal "HTTP/1.1"
31
- response["SERVER_PROTOCOL"].must_equal "HTTP/1.1"
32
- response["SERVER_PORT"].must_equal @port.to_s
33
- response["SERVER_NAME"].must_equal @host
34
- end
35
-
36
- it "have rack headers" do
37
- GET("/test")
38
- response["rack.version"].must_equal [1,3]
39
- assert_equal false, response["rack.multithread"]
40
- assert_equal true, response["rack.multiprocess"]
41
- assert_equal true, response["rack.run_once"]
42
- end
43
-
44
- it "have CGI headers on GET" do
45
- GET("/test")
46
- response["REQUEST_METHOD"].must_equal "GET"
47
- response["SCRIPT_NAME"].must_equal "/test"
48
- response["REQUEST_PATH"].must_equal "/"
49
- response["PATH_INFO"].must_be_nil
50
- response["QUERY_STRING"].must_equal ""
51
- response["test.postdata"].must_equal ""
52
-
53
- GET("/test/foo?quux=1")
54
- response["REQUEST_METHOD"].must_equal "GET"
55
- response["SCRIPT_NAME"].must_equal "/test"
56
- response["REQUEST_PATH"].must_equal "/"
57
- response["PATH_INFO"].must_equal "/foo"
58
- response["QUERY_STRING"].must_equal "quux=1"
59
- end
60
-
61
- it "have CGI headers on POST" do
62
- POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
63
- status.must_equal 200
64
- response["REQUEST_METHOD"].must_equal "POST"
65
- response["SCRIPT_NAME"].must_equal "/test"
66
- response["REQUEST_PATH"].must_equal "/"
67
- response["QUERY_STRING"].must_equal ""
68
- response["HTTP_X_TEST_HEADER"].must_equal "42"
69
- response["test.postdata"].must_equal "rack-form-data=23"
70
- end
71
-
72
- it "support HTTP auth" do
73
- GET("/test", {:user => "ruth", :passwd => "secret"})
74
- response["HTTP_AUTHORIZATION"].must_equal "Basic cnV0aDpzZWNyZXQ="
75
- end
76
-
77
- it "set status" do
78
- GET("/test?secret")
79
- status.must_equal 403
80
- response["rack.url_scheme"].must_equal "http"
81
- end
82
- end
83
-
84
- end # if defined? LIGHTTPD_PID
data/test/spec_chunked.rb DELETED
@@ -1,103 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/chunked'
3
- require 'rack/lint'
4
- require 'rack/mock'
5
-
6
- describe Rack::Chunked do
7
- def chunked(app)
8
- proc do |env|
9
- app = Rack::Chunked.new(app)
10
- response = Rack::Lint.new(app).call(env)
11
- # we want to use body like an array, but it only has #each
12
- response[2] = response[2].to_enum.to_a
13
- response
14
- end
15
- end
16
-
17
- before do
18
- @env = Rack::MockRequest.
19
- env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET')
20
- end
21
-
22
- it 'chunk responses with no Content-Length' do
23
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
24
- response = Rack::MockResponse.new(*chunked(app).call(@env))
25
- response.headers.wont_include 'Content-Length'
26
- response.headers['Transfer-Encoding'].must_equal 'chunked'
27
- response.body.must_equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n"
28
- end
29
-
30
- it 'chunks empty bodies properly' do
31
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, []] }
32
- response = Rack::MockResponse.new(*chunked(app).call(@env))
33
- response.headers.wont_include 'Content-Length'
34
- response.headers['Transfer-Encoding'].must_equal 'chunked'
35
- response.body.must_equal "0\r\n\r\n"
36
- end
37
-
38
- it 'chunks encoded bodies properly' do
39
- body = ["\uFFFEHello", " ", "World"].map {|t| t.encode("UTF-16LE") }
40
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, body] }
41
- response = Rack::MockResponse.new(*chunked(app).call(@env))
42
- response.headers.wont_include 'Content-Length'
43
- response.headers['Transfer-Encoding'].must_equal 'chunked'
44
- response.body.encoding.to_s.must_equal "ASCII-8BIT"
45
- response.body.must_equal "c\r\n\xFE\xFFH\x00e\x00l\x00l\x00o\x00\r\n2\r\n \x00\r\na\r\nW\x00o\x00r\x00l\x00d\x00\r\n0\r\n\r\n".force_encoding("BINARY")
46
- response.body.must_equal "c\r\n\xFE\xFFH\x00e\x00l\x00l\x00o\x00\r\n2\r\n \x00\r\na\r\nW\x00o\x00r\x00l\x00d\x00\r\n0\r\n\r\n".force_encoding(Encoding::BINARY)
47
- end
48
-
49
- it 'not modify response when Content-Length header present' do
50
- app = lambda { |env|
51
- [200, {"Content-Type" => "text/plain", 'Content-Length'=>'12'}, ['Hello', ' ', 'World!']]
52
- }
53
- status, headers, body = chunked(app).call(@env)
54
- status.must_equal 200
55
- headers.wont_include 'Transfer-Encoding'
56
- headers.must_include 'Content-Length'
57
- body.join.must_equal 'Hello World!'
58
- end
59
-
60
- it 'not modify response when client is HTTP/1.0' do
61
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
62
- @env['HTTP_VERSION'] = 'HTTP/1.0'
63
- status, headers, body = chunked(app).call(@env)
64
- status.must_equal 200
65
- headers.wont_include 'Transfer-Encoding'
66
- body.join.must_equal 'Hello World!'
67
- end
68
-
69
- it 'not modify response when client is ancient, pre-HTTP/1.0' do
70
- app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
71
- check = lambda do
72
- status, headers, body = chunked(app).call(@env.dup)
73
- status.must_equal 200
74
- headers.wont_include 'Transfer-Encoding'
75
- body.join.must_equal 'Hello World!'
76
- end
77
-
78
- @env.delete('HTTP_VERSION') # unicorn will do this on pre-HTTP/1.0 requests
79
- check.call
80
-
81
- @env['HTTP_VERSION'] = 'HTTP/0.9' # not sure if this happens in practice
82
- check.call
83
- end
84
-
85
- it 'not modify response when Transfer-Encoding header already present' do
86
- app = lambda { |env|
87
- [200, {"Content-Type" => "text/plain", 'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']]
88
- }
89
- status, headers, body = chunked(app).call(@env)
90
- status.must_equal 200
91
- headers['Transfer-Encoding'].must_equal 'identity'
92
- body.join.must_equal 'Hello World!'
93
- end
94
-
95
- [100, 204, 304].each do |status_code|
96
- it "not modify response when status code is #{status_code}" do
97
- app = lambda { |env| [status_code, {}, []] }
98
- status, headers, _ = chunked(app).call(@env)
99
- status.must_equal status_code
100
- headers.wont_include 'Transfer-Encoding'
101
- end
102
- end
103
- end
@@ -1,107 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/common_logger'
3
- require 'rack/lint'
4
- require 'rack/mock'
5
-
6
- require 'logger'
7
-
8
- describe Rack::CommonLogger do
9
- obj = 'foobar'
10
- length = obj.size
11
-
12
- app = Rack::Lint.new lambda { |env|
13
- [200,
14
- {"Content-Type" => "text/html", "Content-Length" => length.to_s},
15
- [obj]]}
16
- app_without_length = Rack::Lint.new lambda { |env|
17
- [200,
18
- {"Content-Type" => "text/html"},
19
- []]}
20
- app_with_zero_length = Rack::Lint.new lambda { |env|
21
- [200,
22
- {"Content-Type" => "text/html", "Content-Length" => "0"},
23
- []]}
24
- app_without_lint = lambda { |env|
25
- [200,
26
- { "content-type" => "text/html", "content-length" => length.to_s },
27
- [obj]]}
28
-
29
- it "log to rack.errors by default" do
30
- res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/")
31
-
32
- res.errors.wont_be :empty?
33
- res.errors.must_match(/"GET \/ " 200 #{length} /)
34
- end
35
-
36
- it "log to anything with +write+" do
37
- log = StringIO.new
38
- Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
39
-
40
- log.string.must_match(/"GET \/ " 200 #{length} /)
41
- end
42
-
43
- it "work with standartd library logger" do
44
- logdev = StringIO.new
45
- log = Logger.new(logdev)
46
- Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
47
-
48
- logdev.string.must_match(/"GET \/ " 200 #{length} /)
49
- end
50
-
51
- it "log - content length if header is missing" do
52
- res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/")
53
-
54
- res.errors.wont_be :empty?
55
- res.errors.must_match(/"GET \/ " 200 - /)
56
- end
57
-
58
- it "log - content length if header is zero" do
59
- res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/")
60
-
61
- res.errors.wont_be :empty?
62
- res.errors.must_match(/"GET \/ " 200 - /)
63
- end
64
-
65
- def with_mock_time(t = 0)
66
- mc = class << Time; self; end
67
- mc.send :alias_method, :old_now, :now
68
- mc.send :define_method, :now do
69
- at(t)
70
- end
71
- yield
72
- ensure
73
- mc.send :undef_method, :now
74
- mc.send :alias_method, :now, :old_now
75
- end
76
-
77
- it "log in common log format" do
78
- log = StringIO.new
79
- with_mock_time do
80
- Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
81
- end
82
-
83
- md = /- - - \[([^\]]+)\] "(\w+) \/ " (\d{3}) \d+ ([\d\.]+)/.match(log.string)
84
- md.wont_equal nil
85
- time, method, status, duration = *md.captures
86
- time.must_equal Time.at(0).strftime("%d/%b/%Y:%H:%M:%S %z")
87
- method.must_equal "GET"
88
- status.must_equal "200"
89
- (0..1).must_include duration.to_f
90
- end
91
-
92
- it "escapes non printable characters except newline" do
93
- logdev = StringIO.new
94
- log = Logger.new(logdev)
95
- Rack::MockRequest.new(Rack::CommonLogger.new(app_without_lint, log)).request("GET\b", "/hello")
96
-
97
- logdev.string.must_match(/GET\\x8 \/hello/)
98
- end
99
-
100
- def length
101
- 123
102
- end
103
-
104
- def self.obj
105
- "hello world"
106
- end
107
- end