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
@@ -1,510 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack'
3
- require 'rack/response'
4
- require 'stringio'
5
-
6
- describe Rack::Response do
7
- it 'has cache-control methods' do
8
- response = Rack::Response.new
9
- cc = 'foo'
10
- response.cache_control = cc
11
- assert_equal cc, response.cache_control
12
- assert_equal cc, response.to_a[2]['Cache-Control']
13
- end
14
-
15
- it 'has an etag method' do
16
- response = Rack::Response.new
17
- etag = 'foo'
18
- response.etag = etag
19
- assert_equal etag, response.etag
20
- assert_equal etag, response.to_a[2]['ETag']
21
- end
22
-
23
- it "have sensible default values" do
24
- response = Rack::Response.new
25
- status, header, body = response.finish
26
- status.must_equal 200
27
- header.must_equal({})
28
- body.each { |part|
29
- part.must_equal ""
30
- }
31
-
32
- response = Rack::Response.new
33
- status, header, body = *response
34
- status.must_equal 200
35
- header.must_equal({})
36
- body.each { |part|
37
- part.must_equal ""
38
- }
39
- end
40
-
41
- it "can be written to" do
42
- response = Rack::Response.new
43
-
44
- _, _, body = response.finish do
45
- response.write "foo"
46
- response.write "bar"
47
- response.write "baz"
48
- end
49
-
50
- parts = []
51
- body.each { |part| parts << part }
52
-
53
- parts.must_equal ["foo", "bar", "baz"]
54
- end
55
-
56
- it "can set and read headers" do
57
- response = Rack::Response.new
58
- response["Content-Type"].must_equal nil
59
- response["Content-Type"] = "text/plain"
60
- response["Content-Type"].must_equal "text/plain"
61
- end
62
-
63
- it "can override the initial Content-Type with a different case" do
64
- response = Rack::Response.new("", 200, "content-type" => "text/plain")
65
- response["Content-Type"].must_equal "text/plain"
66
- end
67
-
68
- it "can set cookies" do
69
- response = Rack::Response.new
70
-
71
- response.set_cookie "foo", "bar"
72
- response["Set-Cookie"].must_equal "foo=bar"
73
- response.set_cookie "foo2", "bar2"
74
- response["Set-Cookie"].must_equal ["foo=bar", "foo2=bar2"].join("\n")
75
- response.set_cookie "foo3", "bar3"
76
- response["Set-Cookie"].must_equal ["foo=bar", "foo2=bar2", "foo3=bar3"].join("\n")
77
- end
78
-
79
- it "can set cookies with the same name for multiple domains" do
80
- response = Rack::Response.new
81
- response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"}
82
- response.set_cookie "foo", {:value => "bar", :domain => ".example.com"}
83
- response["Set-Cookie"].must_equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n")
84
- end
85
-
86
- it "formats the Cookie expiration date accordingly to RFC 6265" do
87
- response = Rack::Response.new
88
-
89
- response.set_cookie "foo", {:value => "bar", :expires => Time.now+10}
90
- response["Set-Cookie"].must_match(
91
- /expires=..., \d\d ... \d\d\d\d \d\d:\d\d:\d\d .../)
92
- end
93
-
94
- it "can set secure cookies" do
95
- response = Rack::Response.new
96
- response.set_cookie "foo", {:value => "bar", :secure => true}
97
- response["Set-Cookie"].must_equal "foo=bar; secure"
98
- end
99
-
100
- it "can set http only cookies" do
101
- response = Rack::Response.new
102
- response.set_cookie "foo", {:value => "bar", :httponly => true}
103
- response["Set-Cookie"].must_equal "foo=bar; HttpOnly"
104
- end
105
-
106
- it "can set http only cookies with :http_only" do
107
- response = Rack::Response.new
108
- response.set_cookie "foo", {:value => "bar", :http_only => true}
109
- response["Set-Cookie"].must_equal "foo=bar; HttpOnly"
110
- end
111
-
112
- it "can set prefers :httponly for http only cookie setting when :httponly and :http_only provided" do
113
- response = Rack::Response.new
114
- response.set_cookie "foo", {:value => "bar", :httponly => false, :http_only => true}
115
- response["Set-Cookie"].must_equal "foo=bar"
116
- end
117
-
118
- it "can set SameSite cookies with symbol value :lax" do
119
- response = Rack::Response.new
120
- response.set_cookie "foo", {:value => "bar", :same_site => :lax}
121
- response["Set-Cookie"].must_equal "foo=bar; SameSite=Lax"
122
- end
123
-
124
- it "can set SameSite cookies with symbol value :Lax" do
125
- response = Rack::Response.new
126
- response.set_cookie "foo", {:value => "bar", :same_site => :lax}
127
- response["Set-Cookie"].must_equal "foo=bar; SameSite=Lax"
128
- end
129
-
130
- it "can set SameSite cookies with string value 'Lax'" do
131
- response = Rack::Response.new
132
- response.set_cookie "foo", {:value => "bar", :same_site => "Lax"}
133
- response["Set-Cookie"].must_equal "foo=bar; SameSite=Lax"
134
- end
135
-
136
- it "can set SameSite cookies with boolean value true" do
137
- response = Rack::Response.new
138
- response.set_cookie "foo", {:value => "bar", :same_site => true}
139
- response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
140
- end
141
-
142
- it "can set SameSite cookies with symbol value :strict" do
143
- response = Rack::Response.new
144
- response.set_cookie "foo", {:value => "bar", :same_site => :strict}
145
- response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
146
- end
147
-
148
- it "can set SameSite cookies with symbol value :Strict" do
149
- response = Rack::Response.new
150
- response.set_cookie "foo", {:value => "bar", :same_site => :Strict}
151
- response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
152
- end
153
-
154
- it "can set SameSite cookies with string value 'Strict'" do
155
- response = Rack::Response.new
156
- response.set_cookie "foo", {:value => "bar", :same_site => "Strict"}
157
- response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
158
- end
159
-
160
- it "validates the SameSite option value" do
161
- response = Rack::Response.new
162
- lambda {
163
- response.set_cookie "foo", {:value => "bar", :same_site => "Foo"}
164
- }.must_raise(ArgumentError).
165
- message.must_match(/Invalid SameSite value: "Foo"/)
166
- end
167
-
168
- it "can set SameSite cookies with symbol value" do
169
- response = Rack::Response.new
170
- response.set_cookie "foo", {:value => "bar", :same_site => :Strict}
171
- response["Set-Cookie"].must_equal "foo=bar; SameSite=Strict"
172
- end
173
-
174
- [ nil, false ].each do |non_truthy|
175
- it "omits SameSite attribute given a #{non_truthy.inspect} value" do
176
- response = Rack::Response.new
177
- response.set_cookie "foo", {:value => "bar", :same_site => non_truthy}
178
- response["Set-Cookie"].must_equal "foo=bar"
179
- end
180
- end
181
-
182
- it "can delete cookies" do
183
- response = Rack::Response.new
184
- response.set_cookie "foo", "bar"
185
- response.set_cookie "foo2", "bar2"
186
- response.delete_cookie "foo"
187
- response["Set-Cookie"].must_equal [
188
- "foo2=bar2",
189
- "foo=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"
190
- ].join("\n")
191
- end
192
-
193
- it "can delete cookies with the same name from multiple domains" do
194
- response = Rack::Response.new
195
- response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"}
196
- response.set_cookie "foo", {:value => "bar", :domain => ".example.com"}
197
- response["Set-Cookie"].must_equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n")
198
- response.delete_cookie "foo", :domain => ".example.com"
199
- response["Set-Cookie"].must_equal ["foo=bar; domain=sample.example.com", "foo=; domain=.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n")
200
- response.delete_cookie "foo", :domain => "sample.example.com"
201
- response["Set-Cookie"].must_equal ["foo=; domain=.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000",
202
- "foo=; domain=sample.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n")
203
- end
204
-
205
- it "can delete cookies with the same name with different paths" do
206
- response = Rack::Response.new
207
- response.set_cookie "foo", {:value => "bar", :path => "/"}
208
- response.set_cookie "foo", {:value => "bar", :path => "/path"}
209
- response["Set-Cookie"].must_equal ["foo=bar; path=/",
210
- "foo=bar; path=/path"].join("\n")
211
-
212
- response.delete_cookie "foo", :path => "/path"
213
- response["Set-Cookie"].must_equal ["foo=bar; path=/",
214
- "foo=; path=/path; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n")
215
- end
216
-
217
- it "can do redirects" do
218
- response = Rack::Response.new
219
- response.redirect "/foo"
220
- status, header, body = response.finish
221
- status.must_equal 302
222
- header["Location"].must_equal "/foo"
223
-
224
- response = Rack::Response.new
225
- response.redirect "/foo", 307
226
- status, header, body = response.finish
227
-
228
- status.must_equal 307
229
- end
230
-
231
- it "has a useful constructor" do
232
- r = Rack::Response.new("foo")
233
- status, header, body = r.finish
234
- str = ""; body.each { |part| str << part }
235
- str.must_equal "foo"
236
-
237
- r = Rack::Response.new(["foo", "bar"])
238
- status, header, body = r.finish
239
- str = ""; body.each { |part| str << part }
240
- str.must_equal "foobar"
241
-
242
- object_with_each = Object.new
243
- def object_with_each.each
244
- yield "foo"
245
- yield "bar"
246
- end
247
- r = Rack::Response.new(object_with_each)
248
- r.write "foo"
249
- status, header, body = r.finish
250
- str = ""; body.each { |part| str << part }
251
- str.must_equal "foobarfoo"
252
-
253
- r = Rack::Response.new([], 500)
254
- r.status.must_equal 500
255
-
256
- r = Rack::Response.new([], "200 OK")
257
- r.status.must_equal 200
258
- end
259
-
260
- it "has a constructor that can take a block" do
261
- r = Rack::Response.new { |res|
262
- res.status = 404
263
- res.write "foo"
264
- }
265
- status, _, body = r.finish
266
- str = ""; body.each { |part| str << part }
267
- str.must_equal "foo"
268
- status.must_equal 404
269
- end
270
-
271
- it "doesn't return invalid responses" do
272
- r = Rack::Response.new(["foo", "bar"], 204)
273
- _, header, body = r.finish
274
- str = ""; body.each { |part| str << part }
275
- str.must_be :empty?
276
- header["Content-Type"].must_equal nil
277
- header['Content-Length'].must_equal nil
278
-
279
- lambda {
280
- Rack::Response.new(Object.new)
281
- }.must_raise(TypeError).
282
- message.must_match(/stringable or iterable required/)
283
- end
284
-
285
- it "knows if it's empty" do
286
- r = Rack::Response.new
287
- r.must_be :empty?
288
- r.write "foo"
289
- r.wont_be :empty?
290
-
291
- r = Rack::Response.new
292
- r.must_be :empty?
293
- r.finish
294
- r.must_be :empty?
295
-
296
- r = Rack::Response.new
297
- r.must_be :empty?
298
- r.finish { }
299
- r.wont_be :empty?
300
- end
301
-
302
- it "provide access to the HTTP status" do
303
- res = Rack::Response.new
304
- res.status = 200
305
- res.must_be :successful?
306
- res.must_be :ok?
307
-
308
- res.status = 201
309
- res.must_be :successful?
310
- res.must_be :created?
311
-
312
- res.status = 202
313
- res.must_be :successful?
314
- res.must_be :accepted?
315
-
316
- res.status = 204
317
- res.must_be :successful?
318
- res.must_be :no_content?
319
-
320
- res.status = 301
321
- res.must_be :redirect?
322
- res.must_be :moved_permanently?
323
-
324
- res.status = 302
325
- res.must_be :redirect?
326
-
327
- res.status = 303
328
- res.must_be :redirect?
329
-
330
- res.status = 307
331
- res.must_be :redirect?
332
-
333
- res.status = 308
334
- res.must_be :redirect?
335
-
336
- res.status = 400
337
- res.wont_be :successful?
338
- res.must_be :client_error?
339
- res.must_be :bad_request?
340
-
341
- res.status = 401
342
- res.wont_be :successful?
343
- res.must_be :client_error?
344
- res.must_be :unauthorized?
345
-
346
- res.status = 404
347
- res.wont_be :successful?
348
- res.must_be :client_error?
349
- res.must_be :not_found?
350
-
351
- res.status = 405
352
- res.wont_be :successful?
353
- res.must_be :client_error?
354
- res.must_be :method_not_allowed?
355
-
356
- res.status = 412
357
- res.wont_be :successful?
358
- res.must_be :client_error?
359
- res.must_be :precondition_failed?
360
-
361
- res.status = 422
362
- res.wont_be :successful?
363
- res.must_be :client_error?
364
- res.must_be :unprocessable?
365
-
366
- res.status = 501
367
- res.wont_be :successful?
368
- res.must_be :server_error?
369
- end
370
-
371
- it "provide access to the HTTP headers" do
372
- res = Rack::Response.new
373
- res["Content-Type"] = "text/yaml"
374
-
375
- res.must_include "Content-Type"
376
- res.headers["Content-Type"].must_equal "text/yaml"
377
- res["Content-Type"].must_equal "text/yaml"
378
- res.content_type.must_equal "text/yaml"
379
- res.content_length.must_be_nil
380
- res.location.must_be_nil
381
- end
382
-
383
- it "does not add or change Content-Length when #finish()ing" do
384
- res = Rack::Response.new
385
- res.status = 200
386
- res.finish
387
- res.headers["Content-Length"].must_be_nil
388
-
389
- res = Rack::Response.new
390
- res.status = 200
391
- res.headers["Content-Length"] = "10"
392
- res.finish
393
- res.headers["Content-Length"].must_equal "10"
394
- end
395
-
396
- it "updates Content-Length when body appended to using #write" do
397
- res = Rack::Response.new
398
- res.status = 200
399
- res.headers["Content-Length"].must_be_nil
400
- res.write "Hi"
401
- res.headers["Content-Length"].must_equal "2"
402
- res.write " there"
403
- res.headers["Content-Length"].must_equal "8"
404
- end
405
-
406
- it "calls close on #body" do
407
- res = Rack::Response.new
408
- res.body = StringIO.new
409
- res.close
410
- res.body.must_be :closed?
411
- end
412
-
413
- it "calls close on #body when 204, 205, or 304" do
414
- res = Rack::Response.new
415
- res.body = StringIO.new
416
- res.finish
417
- res.body.wont_be :closed?
418
-
419
- res.status = 204
420
- _, _, b = res.finish
421
- res.body.must_be :closed?
422
- b.wont_equal res.body
423
-
424
- res.body = StringIO.new
425
- res.status = 205
426
- _, _, b = res.finish
427
- res.body.must_be :closed?
428
- b.wont_equal res.body
429
-
430
- res.body = StringIO.new
431
- res.status = 304
432
- _, _, b = res.finish
433
- res.body.must_be :closed?
434
- b.wont_equal res.body
435
- end
436
-
437
- it "wraps the body from #to_ary to prevent infinite loops" do
438
- res = Rack::Response.new
439
- res.finish.last.wont_respond_to(:to_ary)
440
- lambda { res.finish.last.to_ary }.must_raise NoMethodError
441
- end
442
- end
443
-
444
- describe Rack::Response, 'headers' do
445
- before do
446
- @response = Rack::Response.new([], 200, { 'Foo' => '1' })
447
- end
448
-
449
- it 'has_header?' do
450
- lambda { @response.has_header? nil }.must_raise NoMethodError
451
-
452
- @response.has_header?('Foo').must_equal true
453
- @response.has_header?('foo').must_equal true
454
- end
455
-
456
- it 'get_header' do
457
- lambda { @response.get_header nil }.must_raise NoMethodError
458
-
459
- @response.get_header('Foo').must_equal '1'
460
- @response.get_header('foo').must_equal '1'
461
- end
462
-
463
- it 'set_header' do
464
- lambda { @response.set_header nil, '1' }.must_raise NoMethodError
465
-
466
- @response.set_header('Foo', '2').must_equal '2'
467
- @response.has_header?('Foo').must_equal true
468
- @response.get_header('Foo').must_equal('2')
469
-
470
- @response.set_header('Foo', nil).must_be_nil
471
- @response.has_header?('Foo').must_equal true
472
- @response.get_header('Foo').must_be_nil
473
- end
474
-
475
- it 'add_header' do
476
- lambda { @response.add_header nil, '1' }.must_raise NoMethodError
477
-
478
- # Add a value to an existing header
479
- @response.add_header('Foo', '2').must_equal '1,2'
480
- @response.get_header('Foo').must_equal '1,2'
481
-
482
- # Add nil to an existing header
483
- @response.add_header('Foo', nil).must_equal '1,2'
484
- @response.get_header('Foo').must_equal '1,2'
485
-
486
- # Add nil to a nonexistent header
487
- @response.add_header('Bar', nil).must_be_nil
488
- @response.has_header?('Bar').must_equal false
489
- @response.get_header('Bar').must_be_nil
490
-
491
- # Add a value to a nonexistent header
492
- @response.add_header('Bar', '1').must_equal '1'
493
- @response.has_header?('Bar').must_equal true
494
- @response.get_header('Bar').must_equal '1'
495
- end
496
-
497
- it 'delete_header' do
498
- lambda { @response.delete_header nil }.must_raise NoMethodError
499
-
500
- @response.delete_header('Foo').must_equal '1'
501
- (!!@response.has_header?('Foo')).must_equal false
502
-
503
- @response.delete_header('Foo').must_be_nil
504
- @response.has_header?('Foo').must_equal false
505
-
506
- @response.set_header('Foo', 1)
507
- @response.delete_header('foo').must_equal 1
508
- @response.has_header?('Foo').must_equal false
509
- end
510
- end
@@ -1,128 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'stringio'
3
- require 'rack/rewindable_input'
4
-
5
- module RewindableTest
6
- extend Minitest::Spec::DSL
7
-
8
- def setup
9
- @rio = Rack::RewindableInput.new(@io)
10
- end
11
-
12
- class << self # HACK to get this running w/ as few changes as possible
13
- alias_method :should, :it
14
- end
15
-
16
- it "be able to handle to read()" do
17
- @rio.read.must_equal "hello world"
18
- end
19
-
20
- it "be able to handle to read(nil)" do
21
- @rio.read(nil).must_equal "hello world"
22
- end
23
-
24
- it "be able to handle to read(length)" do
25
- @rio.read(1).must_equal "h"
26
- end
27
-
28
- it "be able to handle to read(length, buffer)" do
29
- buffer = ""
30
- result = @rio.read(1, buffer)
31
- result.must_equal "h"
32
- result.object_id.must_equal buffer.object_id
33
- end
34
-
35
- it "be able to handle to read(nil, buffer)" do
36
- buffer = ""
37
- result = @rio.read(nil, buffer)
38
- result.must_equal "hello world"
39
- result.object_id.must_equal buffer.object_id
40
- end
41
-
42
- it "rewind to the beginning when #rewind is called" do
43
- @rio.read(1)
44
- @rio.rewind
45
- @rio.read.must_equal "hello world"
46
- end
47
-
48
- it "be able to handle gets" do
49
- @rio.gets.must_equal "hello world"
50
- end
51
-
52
- it "be able to handle each" do
53
- array = []
54
- @rio.each do |data|
55
- array << data
56
- end
57
- array.must_equal ["hello world"]
58
- end
59
-
60
- it "not buffer into a Tempfile if no data has been read yet" do
61
- @rio.instance_variable_get(:@rewindable_io).must_be_nil
62
- end
63
-
64
- it "buffer into a Tempfile when data has been consumed for the first time" do
65
- @rio.read(1)
66
- tempfile = @rio.instance_variable_get(:@rewindable_io)
67
- tempfile.wont_be :nil?
68
- @rio.read(1)
69
- tempfile2 = @rio.instance_variable_get(:@rewindable_io)
70
- tempfile2.path.must_equal tempfile.path
71
- end
72
-
73
- it "close the underlying tempfile upon calling #close" do
74
- @rio.read(1)
75
- tempfile = @rio.instance_variable_get(:@rewindable_io)
76
- @rio.close
77
- tempfile.must_be :closed?
78
- end
79
-
80
- it "be possible to call #close when no data has been buffered yet" do
81
- @rio.close.must_be_nil
82
- end
83
-
84
- it "be possible to call #close multiple times" do
85
- @rio.close.must_be_nil
86
- @rio.close.must_be_nil
87
- end
88
-
89
- after do
90
- @rio.close
91
- @rio = nil
92
- end
93
- end
94
-
95
- describe Rack::RewindableInput do
96
- describe "given an IO object that is already rewindable" do
97
- def setup
98
- @io = StringIO.new("hello world")
99
- super
100
- end
101
-
102
- include RewindableTest
103
- end
104
-
105
- describe "given an IO object that is not rewindable" do
106
- def setup
107
- @io = StringIO.new("hello world")
108
- @io.instance_eval do
109
- undef :rewind
110
- end
111
- super
112
- end
113
-
114
- include RewindableTest
115
- end
116
-
117
- describe "given an IO object whose rewind method raises Errno::ESPIPE" do
118
- def setup
119
- @io = StringIO.new("hello world")
120
- def @io.rewind
121
- raise Errno::ESPIPE, "You can't rewind this!"
122
- end
123
- super
124
- end
125
-
126
- include RewindableTest
127
- end
128
- end
data/test/spec_runtime.rb DELETED
@@ -1,50 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
- require 'rack/runtime'
5
-
6
- describe Rack::Runtime do
7
- def runtime_app(app, *args)
8
- Rack::Lint.new Rack::Runtime.new(app, *args)
9
- end
10
-
11
- def request
12
- Rack::MockRequest.env_for
13
- end
14
-
15
- it "sets X-Runtime is none is set" do
16
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
17
- response = runtime_app(app).call(request)
18
- response[1]['X-Runtime'].must_match(/[\d\.]+/)
19
- end
20
-
21
- it "doesn't set the X-Runtime if it is already set" do
22
- app = lambda { |env| [200, {'Content-Type' => 'text/plain', "X-Runtime" => "foobar"}, "Hello, World!"] }
23
- response = runtime_app(app).call(request)
24
- response[1]['X-Runtime'].must_equal "foobar"
25
- end
26
-
27
- it "allow a suffix to be set" do
28
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
29
- response = runtime_app(app, "Test").call(request)
30
- response[1]['X-Runtime-Test'].must_match(/[\d\.]+/)
31
- end
32
-
33
- it "allow multiple timers to be set" do
34
- app = lambda { |env| sleep 0.1; [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
35
- runtime = runtime_app(app, "App")
36
-
37
- # wrap many times to guarantee a measurable difference
38
- 100.times do |i|
39
- runtime = Rack::Runtime.new(runtime, i.to_s)
40
- end
41
- runtime = Rack::Runtime.new(runtime, "All")
42
-
43
- response = runtime.call(request)
44
-
45
- response[1]['X-Runtime-App'].must_match(/[\d\.]+/)
46
- response[1]['X-Runtime-All'].must_match(/[\d\.]+/)
47
-
48
- Float(response[1]['X-Runtime-All']).must_be :>, Float(response[1]['X-Runtime-App'])
49
- end
50
- end