rack 1.6.11 → 2.2.3

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 (190) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +694 -0
  3. data/CONTRIBUTING.md +136 -0
  4. data/{COPYING → MIT-LICENSE} +4 -2
  5. data/README.rdoc +157 -163
  6. data/Rakefile +38 -32
  7. data/{SPEC → SPEC.rdoc} +41 -13
  8. data/bin/rackup +1 -0
  9. data/contrib/rack_logo.svg +164 -111
  10. data/example/lobster.ru +2 -0
  11. data/example/protectedlobster.rb +4 -2
  12. data/example/protectedlobster.ru +3 -1
  13. data/lib/rack/auth/abstract/handler.rb +3 -1
  14. data/lib/rack/auth/abstract/request.rb +6 -2
  15. data/lib/rack/auth/basic.rb +7 -4
  16. data/lib/rack/auth/digest/md5.rb +13 -11
  17. data/lib/rack/auth/digest/nonce.rb +6 -3
  18. data/lib/rack/auth/digest/params.rb +5 -4
  19. data/lib/rack/auth/digest/request.rb +6 -4
  20. data/lib/rack/body_proxy.rb +21 -15
  21. data/lib/rack/builder.rb +119 -26
  22. data/lib/rack/cascade.rb +28 -12
  23. data/lib/rack/chunked.rb +70 -22
  24. data/lib/rack/common_logger.rb +80 -0
  25. data/lib/rack/{conditionalget.rb → conditional_get.rb} +20 -16
  26. data/lib/rack/config.rb +2 -0
  27. data/lib/rack/content_length.rb +9 -8
  28. data/lib/rack/content_type.rb +5 -4
  29. data/lib/rack/core_ext/regexp.rb +14 -0
  30. data/lib/rack/deflater.rb +60 -70
  31. data/lib/rack/directory.rb +117 -85
  32. data/lib/rack/etag.rb +9 -7
  33. data/lib/rack/events.rb +153 -0
  34. data/lib/rack/file.rb +4 -149
  35. data/lib/rack/files.rb +218 -0
  36. data/lib/rack/handler/cgi.rb +17 -19
  37. data/lib/rack/handler/fastcgi.rb +17 -18
  38. data/lib/rack/handler/lsws.rb +14 -14
  39. data/lib/rack/handler/scgi.rb +22 -21
  40. data/lib/rack/handler/thin.rb +6 -3
  41. data/lib/rack/handler/webrick.rb +39 -32
  42. data/lib/rack/handler.rb +9 -26
  43. data/lib/rack/head.rb +16 -18
  44. data/lib/rack/lint.rb +110 -64
  45. data/lib/rack/lobster.rb +10 -10
  46. data/lib/rack/lock.rb +17 -11
  47. data/lib/rack/logger.rb +4 -2
  48. data/lib/rack/media_type.rb +43 -0
  49. data/lib/rack/{methodoverride.rb → method_override.rb} +10 -8
  50. data/lib/rack/mime.rb +27 -6
  51. data/lib/rack/mock.rb +124 -65
  52. data/lib/rack/multipart/generator.rb +20 -16
  53. data/lib/rack/multipart/parser.rb +273 -162
  54. data/lib/rack/multipart/uploaded_file.rb +15 -8
  55. data/lib/rack/multipart.rb +39 -8
  56. data/lib/rack/{nulllogger.rb → null_logger.rb} +3 -1
  57. data/lib/rack/query_parser.rb +217 -0
  58. data/lib/rack/recursive.rb +11 -9
  59. data/lib/rack/reloader.rb +8 -4
  60. data/lib/rack/request.rb +553 -305
  61. data/lib/rack/response.rb +244 -88
  62. data/lib/rack/rewindable_input.rb +5 -15
  63. data/lib/rack/runtime.rb +12 -18
  64. data/lib/rack/sendfile.rb +17 -15
  65. data/lib/rack/server.rb +125 -47
  66. data/lib/rack/session/abstract/id.rb +217 -93
  67. data/lib/rack/session/cookie.rb +46 -31
  68. data/lib/rack/session/memcache.rb +4 -87
  69. data/lib/rack/session/pool.rb +26 -17
  70. data/lib/rack/show_exceptions.rb +390 -0
  71. data/lib/rack/{showstatus.rb → show_status.rb} +12 -12
  72. data/lib/rack/static.rb +48 -11
  73. data/lib/rack/tempfile_reaper.rb +3 -3
  74. data/lib/rack/urlmap.rb +26 -19
  75. data/lib/rack/utils.rb +212 -294
  76. data/lib/rack/version.rb +29 -0
  77. data/lib/rack.rb +76 -33
  78. data/rack.gemspec +43 -30
  79. metadata +65 -186
  80. data/HISTORY.md +0 -375
  81. data/KNOWN-ISSUES +0 -44
  82. data/lib/rack/backports/uri/common_18.rb +0 -56
  83. data/lib/rack/backports/uri/common_192.rb +0 -52
  84. data/lib/rack/backports/uri/common_193.rb +0 -29
  85. data/lib/rack/commonlogger.rb +0 -72
  86. data/lib/rack/handler/evented_mongrel.rb +0 -8
  87. data/lib/rack/handler/mongrel.rb +0 -106
  88. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  89. data/lib/rack/showexceptions.rb +0 -387
  90. data/lib/rack/utils/okjson.rb +0 -600
  91. data/test/builder/anything.rb +0 -5
  92. data/test/builder/comment.ru +0 -4
  93. data/test/builder/end.ru +0 -5
  94. data/test/builder/line.ru +0 -1
  95. data/test/builder/options.ru +0 -2
  96. data/test/cgi/assets/folder/test.js +0 -1
  97. data/test/cgi/assets/fonts/font.eot +0 -1
  98. data/test/cgi/assets/images/image.png +0 -1
  99. data/test/cgi/assets/index.html +0 -1
  100. data/test/cgi/assets/javascripts/app.js +0 -1
  101. data/test/cgi/assets/stylesheets/app.css +0 -1
  102. data/test/cgi/lighttpd.conf +0 -26
  103. data/test/cgi/rackup_stub.rb +0 -6
  104. data/test/cgi/sample_rackup.ru +0 -5
  105. data/test/cgi/test +0 -9
  106. data/test/cgi/test+directory/test+file +0 -1
  107. data/test/cgi/test.fcgi +0 -8
  108. data/test/cgi/test.ru +0 -5
  109. data/test/gemloader.rb +0 -10
  110. data/test/multipart/bad_robots +0 -259
  111. data/test/multipart/binary +0 -0
  112. data/test/multipart/content_type_and_no_filename +0 -6
  113. data/test/multipart/empty +0 -10
  114. data/test/multipart/fail_16384_nofile +0 -814
  115. data/test/multipart/file1.txt +0 -1
  116. data/test/multipart/filename_and_modification_param +0 -7
  117. data/test/multipart/filename_and_no_name +0 -6
  118. data/test/multipart/filename_with_escaped_quotes +0 -6
  119. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  120. data/test/multipart/filename_with_null_byte +0 -7
  121. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  122. data/test/multipart/filename_with_unescaped_percentages +0 -6
  123. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  124. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  125. data/test/multipart/filename_with_unescaped_quotes +0 -6
  126. data/test/multipart/ie +0 -6
  127. data/test/multipart/invalid_character +0 -6
  128. data/test/multipart/mixed_files +0 -21
  129. data/test/multipart/nested +0 -10
  130. data/test/multipart/none +0 -9
  131. data/test/multipart/semicolon +0 -6
  132. data/test/multipart/text +0 -15
  133. data/test/multipart/three_files_three_fields +0 -31
  134. data/test/multipart/webkit +0 -32
  135. data/test/rackup/config.ru +0 -31
  136. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  137. data/test/spec_auth_basic.rb +0 -81
  138. data/test/spec_auth_digest.rb +0 -259
  139. data/test/spec_body_proxy.rb +0 -85
  140. data/test/spec_builder.rb +0 -223
  141. data/test/spec_cascade.rb +0 -61
  142. data/test/spec_cgi.rb +0 -102
  143. data/test/spec_chunked.rb +0 -101
  144. data/test/spec_commonlogger.rb +0 -93
  145. data/test/spec_conditionalget.rb +0 -102
  146. data/test/spec_config.rb +0 -22
  147. data/test/spec_content_length.rb +0 -85
  148. data/test/spec_content_type.rb +0 -45
  149. data/test/spec_deflater.rb +0 -339
  150. data/test/spec_directory.rb +0 -88
  151. data/test/spec_etag.rb +0 -107
  152. data/test/spec_fastcgi.rb +0 -107
  153. data/test/spec_file.rb +0 -221
  154. data/test/spec_handler.rb +0 -72
  155. data/test/spec_head.rb +0 -45
  156. data/test/spec_lint.rb +0 -550
  157. data/test/spec_lobster.rb +0 -58
  158. data/test/spec_lock.rb +0 -164
  159. data/test/spec_logger.rb +0 -23
  160. data/test/spec_methodoverride.rb +0 -111
  161. data/test/spec_mime.rb +0 -51
  162. data/test/spec_mock.rb +0 -297
  163. data/test/spec_mongrel.rb +0 -182
  164. data/test/spec_multipart.rb +0 -600
  165. data/test/spec_nulllogger.rb +0 -20
  166. data/test/spec_recursive.rb +0 -72
  167. data/test/spec_request.rb +0 -1232
  168. data/test/spec_response.rb +0 -407
  169. data/test/spec_rewindable_input.rb +0 -118
  170. data/test/spec_runtime.rb +0 -49
  171. data/test/spec_sendfile.rb +0 -130
  172. data/test/spec_server.rb +0 -167
  173. data/test/spec_session_abstract_id.rb +0 -53
  174. data/test/spec_session_cookie.rb +0 -410
  175. data/test/spec_session_memcache.rb +0 -321
  176. data/test/spec_session_pool.rb +0 -209
  177. data/test/spec_showexceptions.rb +0 -98
  178. data/test/spec_showstatus.rb +0 -103
  179. data/test/spec_static.rb +0 -145
  180. data/test/spec_tempfile_reaper.rb +0 -63
  181. data/test/spec_thin.rb +0 -91
  182. data/test/spec_urlmap.rb +0 -236
  183. data/test/spec_utils.rb +0 -647
  184. data/test/spec_version.rb +0 -17
  185. data/test/spec_webrick.rb +0 -184
  186. data/test/static/another/index.html +0 -1
  187. data/test/static/index.html +0 -1
  188. data/test/testrequest.rb +0 -78
  189. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  190. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -1,407 +0,0 @@
1
- require 'rack/response'
2
- require 'stringio'
3
-
4
- describe Rack::Response do
5
- should "have sensible default values" do
6
- response = Rack::Response.new
7
- status, header, body = response.finish
8
- status.should.equal 200
9
- header.should.equal({})
10
- body.each { |part|
11
- part.should.equal ""
12
- }
13
-
14
- response = Rack::Response.new
15
- status, header, body = *response
16
- status.should.equal 200
17
- header.should.equal({})
18
- body.each { |part|
19
- part.should.equal ""
20
- }
21
- end
22
-
23
- it "can be written to" do
24
- response = Rack::Response.new
25
-
26
- _, _, body = response.finish do
27
- response.write "foo"
28
- response.write "bar"
29
- response.write "baz"
30
- end
31
-
32
- parts = []
33
- body.each { |part| parts << part }
34
-
35
- parts.should.equal ["foo", "bar", "baz"]
36
- end
37
-
38
- it "can set and read headers" do
39
- response = Rack::Response.new
40
- response["Content-Type"].should.equal nil
41
- response["Content-Type"] = "text/plain"
42
- response["Content-Type"].should.equal "text/plain"
43
- end
44
-
45
- it "can override the initial Content-Type with a different case" do
46
- response = Rack::Response.new("", 200, "content-type" => "text/plain")
47
- response["Content-Type"].should.equal "text/plain"
48
- end
49
-
50
- it "can set cookies" do
51
- response = Rack::Response.new
52
-
53
- response.set_cookie "foo", "bar"
54
- response["Set-Cookie"].should.equal "foo=bar"
55
- response.set_cookie "foo2", "bar2"
56
- response["Set-Cookie"].should.equal ["foo=bar", "foo2=bar2"].join("\n")
57
- response.set_cookie "foo3", "bar3"
58
- response["Set-Cookie"].should.equal ["foo=bar", "foo2=bar2", "foo3=bar3"].join("\n")
59
- end
60
-
61
- it "can set cookies with the same name for multiple domains" do
62
- response = Rack::Response.new
63
- response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"}
64
- response.set_cookie "foo", {:value => "bar", :domain => ".example.com"}
65
- response["Set-Cookie"].should.equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n")
66
- end
67
-
68
- it "formats the Cookie expiration date accordingly to RFC 6265" do
69
- response = Rack::Response.new
70
-
71
- response.set_cookie "foo", {:value => "bar", :expires => Time.now+10}
72
- response["Set-Cookie"].should.match(
73
- /expires=..., \d\d ... \d\d\d\d \d\d:\d\d:\d\d .../)
74
- end
75
-
76
- it "can set secure cookies" do
77
- response = Rack::Response.new
78
- response.set_cookie "foo", {:value => "bar", :secure => true}
79
- response["Set-Cookie"].should.equal "foo=bar; secure"
80
- end
81
-
82
- it "can set http only cookies" do
83
- response = Rack::Response.new
84
- response.set_cookie "foo", {:value => "bar", :httponly => true}
85
- response["Set-Cookie"].should.equal "foo=bar; HttpOnly"
86
- end
87
-
88
- it "can set http only cookies with :http_only" do
89
- response = Rack::Response.new
90
- response.set_cookie "foo", {:value => "bar", :http_only => true}
91
- response["Set-Cookie"].should.equal "foo=bar; HttpOnly"
92
- end
93
-
94
- it "can set prefers :httponly for http only cookie setting when :httponly and :http_only provided" do
95
- response = Rack::Response.new
96
- response.set_cookie "foo", {:value => "bar", :httponly => false, :http_only => true}
97
- response["Set-Cookie"].should.equal "foo=bar"
98
- end
99
-
100
- it "can set SameSite cookies with symbol value :lax" do
101
- response = Rack::Response.new
102
- response.set_cookie "foo", {:value => "bar", :same_site => :lax}
103
- response["Set-Cookie"].should.equal "foo=bar; SameSite=Lax"
104
- end
105
-
106
- it "can set SameSite cookies with symbol value :Lax" do
107
- response = Rack::Response.new
108
- response.set_cookie "foo", {:value => "bar", :same_site => :lax}
109
- response["Set-Cookie"].should.equal "foo=bar; SameSite=Lax"
110
- end
111
-
112
- it "can set SameSite cookies with string value 'Lax'" do
113
- response = Rack::Response.new
114
- response.set_cookie "foo", {:value => "bar", :same_site => "Lax"}
115
- response["Set-Cookie"].should.equal "foo=bar; SameSite=Lax"
116
- end
117
-
118
- it "can set SameSite cookies with boolean value true" do
119
- response = Rack::Response.new
120
- response.set_cookie "foo", {:value => "bar", :same_site => true}
121
- response["Set-Cookie"].should.equal "foo=bar; SameSite=Strict"
122
- end
123
-
124
- it "can set SameSite cookies with symbol value :strict" do
125
- response = Rack::Response.new
126
- response.set_cookie "foo", {:value => "bar", :same_site => :strict}
127
- response["Set-Cookie"].should.equal "foo=bar; SameSite=Strict"
128
- end
129
-
130
- it "can set SameSite cookies with symbol value :Strict" do
131
- response = Rack::Response.new
132
- response.set_cookie "foo", {:value => "bar", :same_site => :Strict}
133
- response["Set-Cookie"].should.equal "foo=bar; SameSite=Strict"
134
- end
135
-
136
- it "can set SameSite cookies with string value 'Strict'" do
137
- response = Rack::Response.new
138
- response.set_cookie "foo", {:value => "bar", :same_site => "Strict"}
139
- response["Set-Cookie"].should.equal "foo=bar; SameSite=Strict"
140
- end
141
-
142
- it "validates the SameSite option value" do
143
- response = Rack::Response.new
144
- lambda {
145
- response.set_cookie "foo", {:value => "bar", :same_site => "Foo"}
146
- }.should.raise(ArgumentError).
147
- message.should.match(/Invalid SameSite value: "Foo"/)
148
- end
149
-
150
- it "can set SameSite cookies with symbol value" do
151
- response = Rack::Response.new
152
- response.set_cookie "foo", {:value => "bar", :same_site => :Strict}
153
- response["Set-Cookie"].should.equal "foo=bar; SameSite=Strict"
154
- end
155
-
156
- [ nil, false ].each do |non_truthy|
157
- it "omits SameSite attribute given a #{non_truthy.inspect} value" do
158
- response = Rack::Response.new
159
- response.set_cookie "foo", {:value => "bar", :same_site => non_truthy}
160
- response["Set-Cookie"].should.equal "foo=bar"
161
- end
162
- end
163
-
164
- it "can delete cookies" do
165
- response = Rack::Response.new
166
- response.set_cookie "foo", "bar"
167
- response.set_cookie "foo2", "bar2"
168
- response.delete_cookie "foo"
169
- response["Set-Cookie"].should.equal [
170
- "foo2=bar2",
171
- "foo=; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"
172
- ].join("\n")
173
- end
174
-
175
- it "can delete cookies with the same name from multiple domains" do
176
- response = Rack::Response.new
177
- response.set_cookie "foo", {:value => "bar", :domain => "sample.example.com"}
178
- response.set_cookie "foo", {:value => "bar", :domain => ".example.com"}
179
- response["Set-Cookie"].should.equal ["foo=bar; domain=sample.example.com", "foo=bar; domain=.example.com"].join("\n")
180
- response.delete_cookie "foo", :domain => ".example.com"
181
- response["Set-Cookie"].should.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")
182
- response.delete_cookie "foo", :domain => "sample.example.com"
183
- response["Set-Cookie"].should.equal ["foo=; domain=.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000",
184
- "foo=; domain=sample.example.com; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n")
185
- end
186
-
187
- it "can delete cookies with the same name with different paths" do
188
- response = Rack::Response.new
189
- response.set_cookie "foo", {:value => "bar", :path => "/"}
190
- response.set_cookie "foo", {:value => "bar", :path => "/path"}
191
- response["Set-Cookie"].should.equal ["foo=bar; path=/",
192
- "foo=bar; path=/path"].join("\n")
193
-
194
- response.delete_cookie "foo", :path => "/path"
195
- response["Set-Cookie"].should.equal ["foo=bar; path=/",
196
- "foo=; path=/path; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000"].join("\n")
197
- end
198
-
199
- it "can do redirects" do
200
- response = Rack::Response.new
201
- response.redirect "/foo"
202
- status, header, body = response.finish
203
- status.should.equal 302
204
- header["Location"].should.equal "/foo"
205
-
206
- response = Rack::Response.new
207
- response.redirect "/foo", 307
208
- status, header, body = response.finish
209
-
210
- status.should.equal 307
211
- end
212
-
213
- it "has a useful constructor" do
214
- r = Rack::Response.new("foo")
215
- status, header, body = r.finish
216
- str = ""; body.each { |part| str << part }
217
- str.should.equal "foo"
218
-
219
- r = Rack::Response.new(["foo", "bar"])
220
- status, header, body = r.finish
221
- str = ""; body.each { |part| str << part }
222
- str.should.equal "foobar"
223
-
224
- object_with_each = Object.new
225
- def object_with_each.each
226
- yield "foo"
227
- yield "bar"
228
- end
229
- r = Rack::Response.new(object_with_each)
230
- r.write "foo"
231
- status, header, body = r.finish
232
- str = ""; body.each { |part| str << part }
233
- str.should.equal "foobarfoo"
234
-
235
- r = Rack::Response.new([], 500)
236
- r.status.should.equal 500
237
-
238
- r = Rack::Response.new([], "200 OK")
239
- r.status.should.equal 200
240
- end
241
-
242
- it "has a constructor that can take a block" do
243
- r = Rack::Response.new { |res|
244
- res.status = 404
245
- res.write "foo"
246
- }
247
- status, _, body = r.finish
248
- str = ""; body.each { |part| str << part }
249
- str.should.equal "foo"
250
- status.should.equal 404
251
- end
252
-
253
- it "doesn't return invalid responses" do
254
- r = Rack::Response.new(["foo", "bar"], 204)
255
- _, header, body = r.finish
256
- str = ""; body.each { |part| str << part }
257
- str.should.be.empty
258
- header["Content-Type"].should.equal nil
259
- header['Content-Length'].should.equal nil
260
-
261
- lambda {
262
- Rack::Response.new(Object.new)
263
- }.should.raise(TypeError).
264
- message.should =~ /stringable or iterable required/
265
- end
266
-
267
- it "knows if it's empty" do
268
- r = Rack::Response.new
269
- r.should.be.empty
270
- r.write "foo"
271
- r.should.not.be.empty
272
-
273
- r = Rack::Response.new
274
- r.should.be.empty
275
- r.finish
276
- r.should.be.empty
277
-
278
- r = Rack::Response.new
279
- r.should.be.empty
280
- r.finish { }
281
- r.should.not.be.empty
282
- end
283
-
284
- should "provide access to the HTTP status" do
285
- res = Rack::Response.new
286
- res.status = 200
287
- res.should.be.successful
288
- res.should.be.ok
289
-
290
- res.status = 201
291
- res.should.be.successful
292
- res.should.be.created
293
-
294
- res.status = 202
295
- res.should.be.successful
296
- res.should.be.accepted
297
-
298
- res.status = 400
299
- res.should.not.be.successful
300
- res.should.be.client_error
301
- res.should.be.bad_request
302
-
303
- res.status = 401
304
- res.should.not.be.successful
305
- res.should.be.client_error
306
- res.should.be.unauthorized
307
-
308
- res.status = 404
309
- res.should.not.be.successful
310
- res.should.be.client_error
311
- res.should.be.not_found
312
-
313
- res.status = 405
314
- res.should.not.be.successful
315
- res.should.be.client_error
316
- res.should.be.method_not_allowed
317
-
318
- res.status = 418
319
- res.should.not.be.successful
320
- res.should.be.client_error
321
- res.should.be.i_m_a_teapot
322
-
323
- res.status = 422
324
- res.should.not.be.successful
325
- res.should.be.client_error
326
- res.should.be.unprocessable
327
-
328
- res.status = 501
329
- res.should.not.be.successful
330
- res.should.be.server_error
331
-
332
- res.status = 307
333
- res.should.be.redirect
334
- end
335
-
336
- should "provide access to the HTTP headers" do
337
- res = Rack::Response.new
338
- res["Content-Type"] = "text/yaml"
339
-
340
- res.should.include "Content-Type"
341
- res.headers["Content-Type"].should.equal "text/yaml"
342
- res["Content-Type"].should.equal "text/yaml"
343
- res.content_type.should.equal "text/yaml"
344
- res.content_length.should.be.nil
345
- res.location.should.be.nil
346
- end
347
-
348
- it "does not add or change Content-Length when #finish()ing" do
349
- res = Rack::Response.new
350
- res.status = 200
351
- res.finish
352
- res.headers["Content-Length"].should.be.nil
353
-
354
- res = Rack::Response.new
355
- res.status = 200
356
- res.headers["Content-Length"] = "10"
357
- res.finish
358
- res.headers["Content-Length"].should.equal "10"
359
- end
360
-
361
- it "updates Content-Length when body appended to using #write" do
362
- res = Rack::Response.new
363
- res.status = 200
364
- res.headers["Content-Length"].should.be.nil
365
- res.write "Hi"
366
- res.headers["Content-Length"].should.equal "2"
367
- res.write " there"
368
- res.headers["Content-Length"].should.equal "8"
369
- end
370
-
371
- it "calls close on #body" do
372
- res = Rack::Response.new
373
- res.body = StringIO.new
374
- res.close
375
- res.body.should.be.closed
376
- end
377
-
378
- it "calls close on #body when 204, 205, or 304" do
379
- res = Rack::Response.new
380
- res.body = StringIO.new
381
- res.finish
382
- res.body.should.not.be.closed
383
-
384
- res.status = 204
385
- _, _, b = res.finish
386
- res.body.should.be.closed
387
- b.should.not.equal res.body
388
-
389
- res.body = StringIO.new
390
- res.status = 205
391
- _, _, b = res.finish
392
- res.body.should.be.closed
393
- b.should.not.equal res.body
394
-
395
- res.body = StringIO.new
396
- res.status = 304
397
- _, _, b = res.finish
398
- res.body.should.be.closed
399
- b.should.not.equal res.body
400
- end
401
-
402
- it "wraps the body from #to_ary to prevent infinite loops" do
403
- res = Rack::Response.new
404
- res.finish.last.should.not.respond_to?(:to_ary)
405
- lambda { res.finish.last.to_ary }.should.raise(NoMethodError)
406
- end
407
- end
@@ -1,118 +0,0 @@
1
- require 'stringio'
2
- require 'rack/rewindable_input'
3
-
4
- shared "a rewindable IO object" do
5
- before do
6
- @rio = Rack::RewindableInput.new(@io)
7
- end
8
-
9
- should "be able to handle to read()" do
10
- @rio.read.should.equal "hello world"
11
- end
12
-
13
- should "be able to handle to read(nil)" do
14
- @rio.read(nil).should.equal "hello world"
15
- end
16
-
17
- should "be able to handle to read(length)" do
18
- @rio.read(1).should.equal "h"
19
- end
20
-
21
- should "be able to handle to read(length, buffer)" do
22
- buffer = ""
23
- result = @rio.read(1, buffer)
24
- result.should.equal "h"
25
- result.object_id.should.equal buffer.object_id
26
- end
27
-
28
- should "be able to handle to read(nil, buffer)" do
29
- buffer = ""
30
- result = @rio.read(nil, buffer)
31
- result.should.equal "hello world"
32
- result.object_id.should.equal buffer.object_id
33
- end
34
-
35
- should "rewind to the beginning when #rewind is called" do
36
- @rio.read(1)
37
- @rio.rewind
38
- @rio.read.should.equal "hello world"
39
- end
40
-
41
- should "be able to handle gets" do
42
- @rio.gets.should == "hello world"
43
- end
44
-
45
- should "be able to handle each" do
46
- array = []
47
- @rio.each do |data|
48
- array << data
49
- end
50
- array.should.equal(["hello world"])
51
- end
52
-
53
- should "not buffer into a Tempfile if no data has been read yet" do
54
- @rio.instance_variable_get(:@rewindable_io).should.be.nil
55
- end
56
-
57
- should "buffer into a Tempfile when data has been consumed for the first time" do
58
- @rio.read(1)
59
- tempfile = @rio.instance_variable_get(:@rewindable_io)
60
- tempfile.should.not.be.nil
61
- @rio.read(1)
62
- tempfile2 = @rio.instance_variable_get(:@rewindable_io)
63
- tempfile2.path.should == tempfile.path
64
- end
65
-
66
- should "close the underlying tempfile upon calling #close" do
67
- @rio.read(1)
68
- tempfile = @rio.instance_variable_get(:@rewindable_io)
69
- @rio.close
70
- tempfile.should.be.closed
71
- end
72
-
73
- should "be possible to call #close when no data has been buffered yet" do
74
- lambda{ @rio.close }.should.not.raise
75
- end
76
-
77
- should "be possible to call #close multiple times" do
78
- lambda{
79
- @rio.close
80
- @rio.close
81
- }.should.not.raise
82
- end
83
-
84
- @rio.close
85
- @rio = nil
86
- end
87
-
88
- describe Rack::RewindableInput do
89
- describe "given an IO object that is already rewindable" do
90
- before do
91
- @io = StringIO.new("hello world")
92
- end
93
-
94
- behaves_like "a rewindable IO object"
95
- end
96
-
97
- describe "given an IO object that is not rewindable" do
98
- before do
99
- @io = StringIO.new("hello world")
100
- @io.instance_eval do
101
- undef :rewind
102
- end
103
- end
104
-
105
- behaves_like "a rewindable IO object"
106
- end
107
-
108
- describe "given an IO object whose rewind method raises Errno::ESPIPE" do
109
- before do
110
- @io = StringIO.new("hello world")
111
- def @io.rewind
112
- raise Errno::ESPIPE, "You can't rewind this!"
113
- end
114
- end
115
-
116
- behaves_like "a rewindable IO object"
117
- end
118
- end
data/test/spec_runtime.rb DELETED
@@ -1,49 +0,0 @@
1
- require 'rack/lint'
2
- require 'rack/mock'
3
- require 'rack/runtime'
4
-
5
- describe Rack::Runtime do
6
- def runtime_app(app, *args)
7
- Rack::Lint.new Rack::Runtime.new(app, *args)
8
- end
9
-
10
- def request
11
- Rack::MockRequest.env_for
12
- end
13
-
14
- it "sets X-Runtime is none is set" do
15
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
16
- response = runtime_app(app).call(request)
17
- response[1]['X-Runtime'].should =~ /[\d\.]+/
18
- end
19
-
20
- it "doesn't set the X-Runtime if it is already set" do
21
- app = lambda { |env| [200, {'Content-Type' => 'text/plain', "X-Runtime" => "foobar"}, "Hello, World!"] }
22
- response = runtime_app(app).call(request)
23
- response[1]['X-Runtime'].should == "foobar"
24
- end
25
-
26
- should "allow a suffix to be set" do
27
- app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
28
- response = runtime_app(app, "Test").call(request)
29
- response[1]['X-Runtime-Test'].should =~ /[\d\.]+/
30
- end
31
-
32
- should "allow multiple timers to be set" do
33
- app = lambda { |env| sleep 0.1; [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
34
- runtime = runtime_app(app, "App")
35
-
36
- # wrap many times to guarantee a measurable difference
37
- 100.times do |i|
38
- runtime = Rack::Runtime.new(runtime, i.to_s)
39
- end
40
- runtime = Rack::Runtime.new(runtime, "All")
41
-
42
- response = runtime.call(request)
43
-
44
- response[1]['X-Runtime-App'].should =~ /[\d\.]+/
45
- response[1]['X-Runtime-All'].should =~ /[\d\.]+/
46
-
47
- Float(response[1]['X-Runtime-All']).should > Float(response[1]['X-Runtime-App'])
48
- end
49
- end
@@ -1,130 +0,0 @@
1
- require 'fileutils'
2
- require 'rack/lint'
3
- require 'rack/sendfile'
4
- require 'rack/mock'
5
- require 'tmpdir'
6
-
7
- describe Rack::File do
8
- should "respond to #to_path" do
9
- Rack::File.new(Dir.pwd).should.respond_to :to_path
10
- end
11
- end
12
-
13
- describe Rack::Sendfile do
14
- def sendfile_body
15
- FileUtils.touch File.join(Dir.tmpdir, "rack_sendfile")
16
- res = ['Hello World']
17
- def res.to_path ; File.join(Dir.tmpdir, "rack_sendfile") ; end
18
- res
19
- end
20
-
21
- def simple_app(body=sendfile_body)
22
- lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
23
- end
24
-
25
- def sendfile_app(body, mappings = [])
26
- Rack::Lint.new Rack::Sendfile.new(simple_app(body), nil, mappings)
27
- end
28
-
29
- def request(headers={}, body=sendfile_body, mappings=[])
30
- yield Rack::MockRequest.new(sendfile_app(body, mappings)).get('/', headers)
31
- end
32
-
33
- def open_file(path)
34
- Class.new(File) do
35
- unless method_defined?(:to_path)
36
- alias :to_path :path
37
- end
38
- end.open(path, 'wb+')
39
- end
40
-
41
- it "does nothing when no X-Sendfile-Type header present" do
42
- request do |response|
43
- response.should.be.ok
44
- response.body.should.equal 'Hello World'
45
- response.headers.should.not.include 'X-Sendfile'
46
- end
47
- end
48
-
49
- it "sets X-Sendfile response header and discards body" do
50
- request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response|
51
- response.should.be.ok
52
- response.body.should.be.empty
53
- response.headers['Content-Length'].should.equal '0'
54
- response.headers['X-Sendfile'].should.equal File.join(Dir.tmpdir, "rack_sendfile")
55
- end
56
- end
57
-
58
- it "sets X-Lighttpd-Send-File response header and discards body" do
59
- request 'HTTP_X_SENDFILE_TYPE' => 'X-Lighttpd-Send-File' do |response|
60
- response.should.be.ok
61
- response.body.should.be.empty
62
- response.headers['Content-Length'].should.equal '0'
63
- response.headers['X-Lighttpd-Send-File'].should.equal File.join(Dir.tmpdir, "rack_sendfile")
64
- end
65
- end
66
-
67
- it "sets X-Accel-Redirect response header and discards body" do
68
- headers = {
69
- 'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect',
70
- 'HTTP_X_ACCEL_MAPPING' => "#{Dir.tmpdir}/=/foo/bar/"
71
- }
72
- request headers do |response|
73
- response.should.be.ok
74
- response.body.should.be.empty
75
- response.headers['Content-Length'].should.equal '0'
76
- response.headers['X-Accel-Redirect'].should.equal '/foo/bar/rack_sendfile'
77
- end
78
- end
79
-
80
- it 'writes to rack.error when no X-Accel-Mapping is specified' do
81
- request 'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect' do |response|
82
- response.should.be.ok
83
- response.body.should.equal 'Hello World'
84
- response.headers.should.not.include 'X-Accel-Redirect'
85
- response.errors.should.include 'X-Accel-Mapping'
86
- end
87
- end
88
-
89
- it 'does nothing when body does not respond to #to_path' do
90
- request({'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile'}, ['Not a file...']) do |response|
91
- response.body.should.equal 'Not a file...'
92
- response.headers.should.not.include 'X-Sendfile'
93
- end
94
- end
95
-
96
- it "sets X-Accel-Redirect response header and discards body when initialized with multiple mappings" do
97
- begin
98
- dir1 = Dir.mktmpdir
99
- dir2 = Dir.mktmpdir
100
-
101
- first_body = open_file(File.join(dir1, 'rack_sendfile'))
102
- first_body.puts 'hello world'
103
-
104
- second_body = open_file(File.join(dir2, 'rack_sendfile'))
105
- second_body.puts 'goodbye world'
106
-
107
- mappings = [
108
- ["#{dir1}/", '/foo/bar/'],
109
- ["#{dir2}/", '/wibble/']
110
- ]
111
-
112
- request({'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect'}, first_body, mappings) do |response|
113
- response.should.be.ok
114
- response.body.should.be.empty
115
- response.headers['Content-Length'].should.equal '0'
116
- response.headers['X-Accel-Redirect'].should.equal '/foo/bar/rack_sendfile'
117
- end
118
-
119
- request({'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect'}, second_body, mappings) do |response|
120
- response.should.be.ok
121
- response.body.should.be.empty
122
- response.headers['Content-Length'].should.equal '0'
123
- response.headers['X-Accel-Redirect'].should.equal '/wibble/rack_sendfile'
124
- end
125
- ensure
126
- FileUtils.remove_entry_secure dir1
127
- FileUtils.remove_entry_secure dir2
128
- end
129
- end
130
- end