rack 2.0.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 (187) hide show
  1. checksums.yaml +4 -4
  2. data/{HISTORY.md → CHANGELOG.md} +220 -155
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +77 -119
  5. data/Rakefile +25 -18
  6. data/SPEC +3 -4
  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.rb +63 -60
  12. data/lib/rack/auth/abstract/handler.rb +3 -1
  13. data/lib/rack/auth/abstract/request.rb +2 -0
  14. data/lib/rack/auth/basic.rb +4 -1
  15. data/lib/rack/auth/digest/md5.rb +9 -7
  16. data/lib/rack/auth/digest/nonce.rb +6 -3
  17. data/lib/rack/auth/digest/params.rb +4 -2
  18. data/lib/rack/auth/digest/request.rb +2 -0
  19. data/lib/rack/body_proxy.rb +3 -6
  20. data/lib/rack/builder.rb +38 -15
  21. data/lib/rack/cascade.rb +6 -5
  22. data/lib/rack/chunked.rb +29 -6
  23. data/lib/rack/common_logger.rb +9 -8
  24. data/lib/rack/conditional_get.rb +3 -1
  25. data/lib/rack/config.rb +2 -0
  26. data/lib/rack/content_length.rb +3 -1
  27. data/lib/rack/content_type.rb +3 -1
  28. data/lib/rack/core_ext/regexp.rb +14 -0
  29. data/lib/rack/deflater.rb +28 -17
  30. data/lib/rack/directory.rb +17 -14
  31. data/lib/rack/etag.rb +3 -1
  32. data/lib/rack/events.rb +5 -3
  33. data/lib/rack/file.rb +5 -173
  34. data/lib/rack/files.rb +178 -0
  35. data/lib/rack/handler.rb +7 -2
  36. data/lib/rack/handler/cgi.rb +3 -1
  37. data/lib/rack/handler/fastcgi.rb +4 -2
  38. data/lib/rack/handler/lsws.rb +3 -1
  39. data/lib/rack/handler/scgi.rb +9 -6
  40. data/lib/rack/handler/thin.rb +3 -1
  41. data/lib/rack/handler/webrick.rb +4 -2
  42. data/lib/rack/head.rb +2 -0
  43. data/lib/rack/lint.rb +14 -11
  44. data/lib/rack/lobster.rb +7 -5
  45. data/lib/rack/lock.rb +2 -0
  46. data/lib/rack/logger.rb +2 -0
  47. data/lib/rack/media_type.rb +10 -5
  48. data/lib/rack/method_override.rb +9 -3
  49. data/lib/rack/mime.rb +9 -1
  50. data/lib/rack/mock.rb +74 -15
  51. data/lib/rack/multipart.rb +5 -3
  52. data/lib/rack/multipart/generator.rb +6 -7
  53. data/lib/rack/multipart/parser.rb +54 -51
  54. data/lib/rack/multipart/uploaded_file.rb +2 -0
  55. data/lib/rack/null_logger.rb +2 -0
  56. data/lib/rack/query_parser.rb +51 -25
  57. data/lib/rack/recursive.rb +7 -5
  58. data/lib/rack/reloader.rb +10 -4
  59. data/lib/rack/request.rb +89 -23
  60. data/lib/rack/response.rb +71 -31
  61. data/lib/rack/rewindable_input.rb +4 -2
  62. data/lib/rack/runtime.rb +4 -2
  63. data/lib/rack/sendfile.rb +15 -8
  64. data/lib/rack/server.rb +88 -16
  65. data/lib/rack/session/abstract/id.rb +104 -21
  66. data/lib/rack/session/cookie.rb +21 -11
  67. data/lib/rack/session/memcache.rb +4 -87
  68. data/lib/rack/session/pool.rb +17 -8
  69. data/lib/rack/show_exceptions.rb +16 -10
  70. data/lib/rack/show_status.rb +4 -2
  71. data/lib/rack/static.rb +15 -10
  72. data/lib/rack/tempfile_reaper.rb +2 -0
  73. data/lib/rack/urlmap.rb +11 -2
  74. data/lib/rack/utils.rb +55 -70
  75. data/rack.gemspec +19 -9
  76. metadata +32 -173
  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 -95
  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 -515
  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 -96
  157. data/test/spec_mime.rb +0 -51
  158. data/test/spec_mock.rb +0 -359
  159. data/test/spec_multipart.rb +0 -722
  160. data/test/spec_null_logger.rb +0 -21
  161. data/test/spec_recursive.rb +0 -75
  162. data/test/spec_request.rb +0 -1393
  163. data/test/spec_response.rb +0 -510
  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 -320
  172. data/test/spec_session_pool.rb +0 -210
  173. data/test/spec_show_exceptions.rb +0 -80
  174. data/test/spec_show_status.rb +0 -104
  175. data/test/spec_static.rb +0 -184
  176. data/test/spec_tempfile_reaper.rb +0 -64
  177. data/test/spec_thin.rb +0 -96
  178. data/test/spec_urlmap.rb +0 -237
  179. data/test/spec_utils.rb +0 -742
  180. data/test/spec_version.rb +0 -11
  181. data/test/spec_webrick.rb +0 -206
  182. data/test/static/another/index.html +0 -1
  183. data/test/static/foo.html +0 -1
  184. data/test/static/index.html +0 -1
  185. data/test/testrequest.rb +0 -78
  186. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  187. 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_be_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_be_nil
277
- header['Content-Length'].must_be_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 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.wont_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