rack 1.0.1 → 2.2.21

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 (147) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +829 -0
  3. data/CONTRIBUTING.md +136 -0
  4. data/{COPYING → MIT-LICENSE} +4 -2
  5. data/README.rdoc +355 -0
  6. data/Rakefile +64 -98
  7. data/SPEC.rdoc +292 -0
  8. data/bin/rackup +3 -174
  9. data/contrib/rack.png +0 -0
  10. data/contrib/rack.svg +150 -0
  11. data/contrib/rack_logo.svg +164 -111
  12. data/contrib/rdoc.css +412 -0
  13. data/example/lobster.ru +2 -0
  14. data/example/protectedlobster.rb +4 -2
  15. data/example/protectedlobster.ru +3 -1
  16. data/lib/rack/auth/abstract/handler.rb +7 -5
  17. data/lib/rack/auth/abstract/request.rb +12 -2
  18. data/lib/rack/auth/basic.rb +6 -4
  19. data/lib/rack/auth/digest/md5.rb +20 -13
  20. data/lib/rack/auth/digest/nonce.rb +6 -4
  21. data/lib/rack/auth/digest/params.rb +11 -12
  22. data/lib/rack/auth/digest/request.rb +15 -12
  23. data/lib/rack/body_proxy.rb +45 -0
  24. data/lib/rack/builder.rb +213 -19
  25. data/lib/rack/cascade.rb +50 -18
  26. data/lib/rack/chunked.rb +95 -27
  27. data/lib/rack/common_logger.rb +84 -0
  28. data/lib/rack/conditional_get.rb +83 -0
  29. data/lib/rack/config.rb +22 -0
  30. data/lib/rack/content_length.rb +19 -10
  31. data/lib/rack/content_type.rb +12 -5
  32. data/lib/rack/core_ext/regexp.rb +14 -0
  33. data/lib/rack/deflater.rb +90 -42
  34. data/lib/rack/directory.rb +118 -72
  35. data/lib/rack/etag.rb +77 -0
  36. data/lib/rack/events.rb +153 -0
  37. data/lib/rack/file.rb +4 -85
  38. data/lib/rack/files.rb +218 -0
  39. data/lib/rack/handler/cgi.rb +22 -24
  40. data/lib/rack/handler/fastcgi.rb +34 -24
  41. data/lib/rack/handler/lsws.rb +16 -15
  42. data/lib/rack/handler/scgi.rb +38 -29
  43. data/lib/rack/handler/thin.rb +23 -7
  44. data/lib/rack/handler/webrick.rb +95 -37
  45. data/lib/rack/handler.rb +49 -14
  46. data/lib/rack/head.rb +19 -13
  47. data/lib/rack/lint.rb +466 -217
  48. data/lib/rack/lobster.rb +19 -14
  49. data/lib/rack/lock.rb +24 -8
  50. data/lib/rack/logger.rb +20 -0
  51. data/lib/rack/media_type.rb +53 -0
  52. data/lib/rack/method_override.rb +52 -0
  53. data/lib/rack/mime.rb +652 -171
  54. data/lib/rack/mock.rb +203 -64
  55. data/lib/rack/multipart/generator.rb +97 -0
  56. data/lib/rack/multipart/parser.rb +440 -0
  57. data/lib/rack/multipart/uploaded_file.rb +41 -0
  58. data/lib/rack/multipart.rb +64 -0
  59. data/lib/rack/null_logger.rb +39 -0
  60. data/lib/rack/query_parser.rb +266 -0
  61. data/lib/rack/recursive.rb +18 -11
  62. data/lib/rack/reloader.rb +13 -5
  63. data/lib/rack/request.rb +607 -191
  64. data/lib/rack/response.rb +245 -110
  65. data/lib/rack/rewindable_input.rb +15 -21
  66. data/lib/rack/runtime.rb +34 -0
  67. data/lib/rack/sendfile.rb +192 -0
  68. data/lib/rack/server.rb +466 -0
  69. data/lib/rack/session/abstract/id.rb +449 -68
  70. data/lib/rack/session/cookie.rb +159 -47
  71. data/lib/rack/session/memcache.rb +4 -103
  72. data/lib/rack/session/pool.rb +39 -49
  73. data/lib/rack/show_exceptions.rb +390 -0
  74. data/lib/rack/{showstatus.rb → show_status.rb} +21 -14
  75. data/lib/rack/static.rb +164 -14
  76. data/lib/rack/tempfile_reaper.rb +22 -0
  77. data/lib/rack/urlmap.rb +60 -18
  78. data/lib/rack/utils.rb +508 -277
  79. data/lib/rack/version.rb +29 -0
  80. data/lib/rack.rb +85 -34
  81. data/rack.gemspec +43 -51
  82. metadata +119 -207
  83. data/KNOWN-ISSUES +0 -18
  84. data/RDOX +0 -428
  85. data/README +0 -364
  86. data/SPEC +0 -164
  87. data/lib/rack/adapter/camping.rb +0 -22
  88. data/lib/rack/auth/openid.rb +0 -480
  89. data/lib/rack/commonlogger.rb +0 -61
  90. data/lib/rack/conditionalget.rb +0 -47
  91. data/lib/rack/handler/evented_mongrel.rb +0 -8
  92. data/lib/rack/handler/mongrel.rb +0 -87
  93. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  94. data/lib/rack/methodoverride.rb +0 -27
  95. data/lib/rack/showexceptions.rb +0 -349
  96. data/test/cgi/lighttpd.conf +0 -20
  97. data/test/cgi/test +0 -9
  98. data/test/cgi/test.fcgi +0 -8
  99. data/test/cgi/test.ru +0 -7
  100. data/test/multipart/binary +0 -0
  101. data/test/multipart/empty +0 -10
  102. data/test/multipart/ie +0 -6
  103. data/test/multipart/nested +0 -10
  104. data/test/multipart/none +0 -9
  105. data/test/multipart/semicolon +0 -6
  106. data/test/multipart/text +0 -10
  107. data/test/spec_rack_auth_basic.rb +0 -73
  108. data/test/spec_rack_auth_digest.rb +0 -226
  109. data/test/spec_rack_auth_openid.rb +0 -84
  110. data/test/spec_rack_builder.rb +0 -84
  111. data/test/spec_rack_camping.rb +0 -51
  112. data/test/spec_rack_cascade.rb +0 -50
  113. data/test/spec_rack_cgi.rb +0 -89
  114. data/test/spec_rack_chunked.rb +0 -62
  115. data/test/spec_rack_commonlogger.rb +0 -32
  116. data/test/spec_rack_conditionalget.rb +0 -41
  117. data/test/spec_rack_content_length.rb +0 -43
  118. data/test/spec_rack_content_type.rb +0 -30
  119. data/test/spec_rack_deflater.rb +0 -127
  120. data/test/spec_rack_directory.rb +0 -61
  121. data/test/spec_rack_fastcgi.rb +0 -89
  122. data/test/spec_rack_file.rb +0 -75
  123. data/test/spec_rack_handler.rb +0 -43
  124. data/test/spec_rack_head.rb +0 -30
  125. data/test/spec_rack_lint.rb +0 -521
  126. data/test/spec_rack_lobster.rb +0 -45
  127. data/test/spec_rack_lock.rb +0 -38
  128. data/test/spec_rack_methodoverride.rb +0 -60
  129. data/test/spec_rack_mock.rb +0 -157
  130. data/test/spec_rack_mongrel.rb +0 -189
  131. data/test/spec_rack_recursive.rb +0 -77
  132. data/test/spec_rack_request.rb +0 -504
  133. data/test/spec_rack_response.rb +0 -218
  134. data/test/spec_rack_rewindable_input.rb +0 -118
  135. data/test/spec_rack_session_cookie.rb +0 -82
  136. data/test/spec_rack_session_memcache.rb +0 -240
  137. data/test/spec_rack_session_pool.rb +0 -172
  138. data/test/spec_rack_showexceptions.rb +0 -21
  139. data/test/spec_rack_showstatus.rb +0 -72
  140. data/test/spec_rack_static.rb +0 -37
  141. data/test/spec_rack_thin.rb +0 -91
  142. data/test/spec_rack_urlmap.rb +0 -185
  143. data/test/spec_rack_utils.rb +0 -387
  144. data/test/spec_rack_webrick.rb +0 -130
  145. data/test/testrequest.rb +0 -57
  146. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  147. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -1,521 +0,0 @@
1
- require 'test/spec'
2
- require 'stringio'
3
-
4
- require 'rack/lint'
5
- require 'rack/mock'
6
-
7
- context "Rack::Lint" do
8
- def env(*args)
9
- Rack::MockRequest.env_for("/", *args)
10
- end
11
-
12
- specify "passes valid request" do
13
- lambda {
14
- Rack::Lint.new(lambda { |env|
15
- [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]]
16
- }).call(env({}))
17
- }.should.not.raise
18
- end
19
-
20
- specify "notices fatal errors" do
21
- lambda { Rack::Lint.new(nil).call }.should.raise(Rack::Lint::LintError).
22
- message.should.match(/No env given/)
23
- end
24
-
25
- specify "notices environment errors" do
26
- lambda { Rack::Lint.new(nil).call 5 }.should.raise(Rack::Lint::LintError).
27
- message.should.match(/not a Hash/)
28
-
29
- lambda {
30
- e = env
31
- e.delete("REQUEST_METHOD")
32
- Rack::Lint.new(nil).call(e)
33
- }.should.raise(Rack::Lint::LintError).
34
- message.should.match(/missing required key REQUEST_METHOD/)
35
-
36
- lambda {
37
- e = env
38
- e.delete("SERVER_NAME")
39
- Rack::Lint.new(nil).call(e)
40
- }.should.raise(Rack::Lint::LintError).
41
- message.should.match(/missing required key SERVER_NAME/)
42
-
43
-
44
- lambda {
45
- Rack::Lint.new(nil).call(env("HTTP_CONTENT_TYPE" => "text/plain"))
46
- }.should.raise(Rack::Lint::LintError).
47
- message.should.match(/contains HTTP_CONTENT_TYPE/)
48
-
49
- lambda {
50
- Rack::Lint.new(nil).call(env("HTTP_CONTENT_LENGTH" => "42"))
51
- }.should.raise(Rack::Lint::LintError).
52
- message.should.match(/contains HTTP_CONTENT_LENGTH/)
53
-
54
- lambda {
55
- Rack::Lint.new(nil).call(env("FOO" => Object.new))
56
- }.should.raise(Rack::Lint::LintError).
57
- message.should.match(/non-string value/)
58
-
59
- lambda {
60
- Rack::Lint.new(nil).call(env("rack.version" => "0.2"))
61
- }.should.raise(Rack::Lint::LintError).
62
- message.should.match(/must be an Array/)
63
-
64
- lambda {
65
- Rack::Lint.new(nil).call(env("rack.url_scheme" => "gopher"))
66
- }.should.raise(Rack::Lint::LintError).
67
- message.should.match(/url_scheme unknown/)
68
-
69
- lambda {
70
- Rack::Lint.new(nil).call(env("rack.session" => []))
71
- }.should.raise(Rack::Lint::LintError).
72
- message.should.equal("session [] must respond to store and []=")
73
-
74
- lambda {
75
- Rack::Lint.new(nil).call(env("REQUEST_METHOD" => "FUCKUP?"))
76
- }.should.raise(Rack::Lint::LintError).
77
- message.should.match(/REQUEST_METHOD/)
78
-
79
- lambda {
80
- Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "howdy"))
81
- }.should.raise(Rack::Lint::LintError).
82
- message.should.match(/must start with/)
83
-
84
- lambda {
85
- Rack::Lint.new(nil).call(env("PATH_INFO" => "../foo"))
86
- }.should.raise(Rack::Lint::LintError).
87
- message.should.match(/must start with/)
88
-
89
- lambda {
90
- Rack::Lint.new(nil).call(env("CONTENT_LENGTH" => "xcii"))
91
- }.should.raise(Rack::Lint::LintError).
92
- message.should.match(/Invalid CONTENT_LENGTH/)
93
-
94
- lambda {
95
- e = env
96
- e.delete("PATH_INFO")
97
- e.delete("SCRIPT_NAME")
98
- Rack::Lint.new(nil).call(e)
99
- }.should.raise(Rack::Lint::LintError).
100
- message.should.match(/One of .* must be set/)
101
-
102
- lambda {
103
- Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "/"))
104
- }.should.raise(Rack::Lint::LintError).
105
- message.should.match(/cannot be .* make it ''/)
106
- end
107
-
108
- specify "notices input errors" do
109
- lambda {
110
- Rack::Lint.new(nil).call(env("rack.input" => ""))
111
- }.should.raise(Rack::Lint::LintError).
112
- message.should.match(/does not respond to #gets/)
113
-
114
- lambda {
115
- input = Object.new
116
- def input.binmode?
117
- false
118
- end
119
- Rack::Lint.new(nil).call(env("rack.input" => input))
120
- }.should.raise(Rack::Lint::LintError).
121
- message.should.match(/is not opened in binary mode/)
122
-
123
- lambda {
124
- input = Object.new
125
- def input.external_encoding
126
- result = Object.new
127
- def result.name
128
- "US-ASCII"
129
- end
130
- result
131
- end
132
- Rack::Lint.new(nil).call(env("rack.input" => input))
133
- }.should.raise(Rack::Lint::LintError).
134
- message.should.match(/does not have ASCII-8BIT as its external encoding/)
135
- end
136
-
137
- specify "notices error errors" do
138
- lambda {
139
- Rack::Lint.new(nil).call(env("rack.errors" => ""))
140
- }.should.raise(Rack::Lint::LintError).
141
- message.should.match(/does not respond to #puts/)
142
- end
143
-
144
- specify "notices status errors" do
145
- lambda {
146
- Rack::Lint.new(lambda { |env|
147
- ["cc", {}, ""]
148
- }).call(env({}))
149
- }.should.raise(Rack::Lint::LintError).
150
- message.should.match(/must be >=100 seen as integer/)
151
-
152
- lambda {
153
- Rack::Lint.new(lambda { |env|
154
- [42, {}, ""]
155
- }).call(env({}))
156
- }.should.raise(Rack::Lint::LintError).
157
- message.should.match(/must be >=100 seen as integer/)
158
- end
159
-
160
- specify "notices header errors" do
161
- lambda {
162
- Rack::Lint.new(lambda { |env|
163
- [200, Object.new, []]
164
- }).call(env({}))
165
- }.should.raise(Rack::Lint::LintError).
166
- message.should.equal("headers object should respond to #each, but doesn't (got Object as headers)")
167
-
168
- lambda {
169
- Rack::Lint.new(lambda { |env|
170
- [200, {true=>false}, []]
171
- }).call(env({}))
172
- }.should.raise(Rack::Lint::LintError).
173
- message.should.equal("header key must be a string, was TrueClass")
174
-
175
- lambda {
176
- Rack::Lint.new(lambda { |env|
177
- [200, {"Status" => "404"}, []]
178
- }).call(env({}))
179
- }.should.raise(Rack::Lint::LintError).
180
- message.should.match(/must not contain Status/)
181
-
182
- lambda {
183
- Rack::Lint.new(lambda { |env|
184
- [200, {"Content-Type:" => "text/plain"}, []]
185
- }).call(env({}))
186
- }.should.raise(Rack::Lint::LintError).
187
- message.should.match(/must not contain :/)
188
-
189
- lambda {
190
- Rack::Lint.new(lambda { |env|
191
- [200, {"Content-" => "text/plain"}, []]
192
- }).call(env({}))
193
- }.should.raise(Rack::Lint::LintError).
194
- message.should.match(/must not end/)
195
-
196
- lambda {
197
- Rack::Lint.new(lambda { |env|
198
- [200, {"..%%quark%%.." => "text/plain"}, []]
199
- }).call(env({}))
200
- }.should.raise(Rack::Lint::LintError).
201
- message.should.equal("invalid header name: ..%%quark%%..")
202
-
203
- lambda {
204
- Rack::Lint.new(lambda { |env|
205
- [200, {"Foo" => Object.new}, []]
206
- }).call(env({}))
207
- }.should.raise(Rack::Lint::LintError).
208
- message.should.equal("a header value must be a String, but the value of 'Foo' is a Object")
209
-
210
- lambda {
211
- Rack::Lint.new(lambda { |env|
212
- [200, {"Foo" => [1, 2, 3]}, []]
213
- }).call(env({}))
214
- }.should.raise(Rack::Lint::LintError).
215
- message.should.equal("a header value must be a String, but the value of 'Foo' is a Array")
216
-
217
-
218
- lambda {
219
- Rack::Lint.new(lambda { |env|
220
- [200, {"Foo-Bar" => "text\000plain"}, []]
221
- }).call(env({}))
222
- }.should.raise(Rack::Lint::LintError).
223
- message.should.match(/invalid header/)
224
-
225
- # line ends (010) should be allowed in header values.
226
- lambda {
227
- Rack::Lint.new(lambda { |env|
228
- [200, {"Foo-Bar" => "one\ntwo\nthree", "Content-Length" => "0", "Content-Type" => "text/plain" }, []]
229
- }).call(env({}))
230
- }.should.not.raise(Rack::Lint::LintError)
231
- end
232
-
233
- specify "notices content-type errors" do
234
- lambda {
235
- Rack::Lint.new(lambda { |env|
236
- [200, {"Content-length" => "0"}, []]
237
- }).call(env({}))
238
- }.should.raise(Rack::Lint::LintError).
239
- message.should.match(/No Content-Type/)
240
-
241
- [100, 101, 204, 304].each do |status|
242
- lambda {
243
- Rack::Lint.new(lambda { |env|
244
- [status, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
245
- }).call(env({}))
246
- }.should.raise(Rack::Lint::LintError).
247
- message.should.match(/Content-Type header found/)
248
- end
249
- end
250
-
251
- specify "notices content-length errors" do
252
- [100, 101, 204, 304].each do |status|
253
- lambda {
254
- Rack::Lint.new(lambda { |env|
255
- [status, {"Content-length" => "0"}, []]
256
- }).call(env({}))
257
- }.should.raise(Rack::Lint::LintError).
258
- message.should.match(/Content-Length header found/)
259
- end
260
-
261
- lambda {
262
- Rack::Lint.new(lambda { |env|
263
- [200, {"Content-type" => "text/plain", "Content-Length" => "1"}, []]
264
- }).call(env({}))
265
- }.should.raise(Rack::Lint::LintError).
266
- message.should.match(/Content-Length header was 1, but should be 0/)
267
- end
268
-
269
- specify "notices body errors" do
270
- lambda {
271
- status, header, body = Rack::Lint.new(lambda { |env|
272
- [200, {"Content-type" => "text/plain","Content-length" => "3"}, [1,2,3]]
273
- }).call(env({}))
274
- body.each { |part| }
275
- }.should.raise(Rack::Lint::LintError).
276
- message.should.match(/yielded non-string/)
277
- end
278
-
279
- specify "notices input handling errors" do
280
- lambda {
281
- Rack::Lint.new(lambda { |env|
282
- env["rack.input"].gets("\r\n")
283
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
284
- }).call(env({}))
285
- }.should.raise(Rack::Lint::LintError).
286
- message.should.match(/gets called with arguments/)
287
-
288
- lambda {
289
- Rack::Lint.new(lambda { |env|
290
- env["rack.input"].read(1, 2, 3)
291
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
292
- }).call(env({}))
293
- }.should.raise(Rack::Lint::LintError).
294
- message.should.match(/read called with too many arguments/)
295
-
296
- lambda {
297
- Rack::Lint.new(lambda { |env|
298
- env["rack.input"].read("foo")
299
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
300
- }).call(env({}))
301
- }.should.raise(Rack::Lint::LintError).
302
- message.should.match(/read called with non-integer and non-nil length/)
303
-
304
- lambda {
305
- Rack::Lint.new(lambda { |env|
306
- env["rack.input"].read(-1)
307
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
308
- }).call(env({}))
309
- }.should.raise(Rack::Lint::LintError).
310
- message.should.match(/read called with a negative length/)
311
-
312
- lambda {
313
- Rack::Lint.new(lambda { |env|
314
- env["rack.input"].read(nil, nil)
315
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
316
- }).call(env({}))
317
- }.should.raise(Rack::Lint::LintError).
318
- message.should.match(/read called with non-String buffer/)
319
-
320
- lambda {
321
- Rack::Lint.new(lambda { |env|
322
- env["rack.input"].read(nil, 1)
323
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
324
- }).call(env({}))
325
- }.should.raise(Rack::Lint::LintError).
326
- message.should.match(/read called with non-String buffer/)
327
-
328
- lambda {
329
- Rack::Lint.new(lambda { |env|
330
- env["rack.input"].rewind(0)
331
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
332
- }).call(env({}))
333
- }.should.raise(Rack::Lint::LintError).
334
- message.should.match(/rewind called with arguments/)
335
-
336
- weirdio = Object.new
337
- class << weirdio
338
- def gets
339
- 42
340
- end
341
-
342
- def read
343
- 23
344
- end
345
-
346
- def each
347
- yield 23
348
- yield 42
349
- end
350
-
351
- def rewind
352
- raise Errno::ESPIPE, "Errno::ESPIPE"
353
- end
354
- end
355
-
356
- eof_weirdio = Object.new
357
- class << eof_weirdio
358
- def gets
359
- nil
360
- end
361
-
362
- def read(*args)
363
- nil
364
- end
365
-
366
- def each
367
- end
368
-
369
- def rewind
370
- end
371
- end
372
-
373
- lambda {
374
- Rack::Lint.new(lambda { |env|
375
- env["rack.input"].gets
376
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
377
- }).call(env("rack.input" => weirdio))
378
- }.should.raise(Rack::Lint::LintError).
379
- message.should.match(/gets didn't return a String/)
380
-
381
- lambda {
382
- Rack::Lint.new(lambda { |env|
383
- env["rack.input"].each { |x| }
384
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
385
- }).call(env("rack.input" => weirdio))
386
- }.should.raise(Rack::Lint::LintError).
387
- message.should.match(/each didn't yield a String/)
388
-
389
- lambda {
390
- Rack::Lint.new(lambda { |env|
391
- env["rack.input"].read
392
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
393
- }).call(env("rack.input" => weirdio))
394
- }.should.raise(Rack::Lint::LintError).
395
- message.should.match(/read didn't return nil or a String/)
396
-
397
- lambda {
398
- Rack::Lint.new(lambda { |env|
399
- env["rack.input"].read
400
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
401
- }).call(env("rack.input" => eof_weirdio))
402
- }.should.raise(Rack::Lint::LintError).
403
- message.should.match(/read\(nil\) returned nil on EOF/)
404
-
405
- lambda {
406
- Rack::Lint.new(lambda { |env|
407
- env["rack.input"].rewind
408
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
409
- }).call(env("rack.input" => weirdio))
410
- }.should.raise(Rack::Lint::LintError).
411
- message.should.match(/rewind raised Errno::ESPIPE/)
412
-
413
-
414
- lambda {
415
- Rack::Lint.new(lambda { |env|
416
- env["rack.input"].close
417
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
418
- }).call(env({}))
419
- }.should.raise(Rack::Lint::LintError).
420
- message.should.match(/close must not be called/)
421
- end
422
-
423
- specify "notices error handling errors" do
424
- lambda {
425
- Rack::Lint.new(lambda { |env|
426
- env["rack.errors"].write(42)
427
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
428
- }).call(env({}))
429
- }.should.raise(Rack::Lint::LintError).
430
- message.should.match(/write not called with a String/)
431
-
432
- lambda {
433
- Rack::Lint.new(lambda { |env|
434
- env["rack.errors"].close
435
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
436
- }).call(env({}))
437
- }.should.raise(Rack::Lint::LintError).
438
- message.should.match(/close must not be called/)
439
- end
440
-
441
- specify "notices HEAD errors" do
442
- lambda {
443
- Rack::Lint.new(lambda { |env|
444
- [200, {"Content-type" => "test/plain", "Content-length" => "3"}, []]
445
- }).call(env({"REQUEST_METHOD" => "HEAD"}))
446
- }.should.not.raise
447
-
448
- lambda {
449
- Rack::Lint.new(lambda { |env|
450
- [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]]
451
- }).call(env({"REQUEST_METHOD" => "HEAD"}))
452
- }.should.raise(Rack::Lint::LintError).
453
- message.should.match(/body was given for HEAD/)
454
- end
455
-
456
- specify "passes valid read calls" do
457
- lambda {
458
- Rack::Lint.new(lambda { |env|
459
- env["rack.input"].read
460
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
461
- }).call(env({"rack.input" => StringIO.new("hello world")}))
462
- }.should.not.raise(Rack::Lint::LintError)
463
-
464
- lambda {
465
- Rack::Lint.new(lambda { |env|
466
- env["rack.input"].read(0)
467
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
468
- }).call(env({"rack.input" => StringIO.new("hello world")}))
469
- }.should.not.raise(Rack::Lint::LintError)
470
-
471
- lambda {
472
- Rack::Lint.new(lambda { |env|
473
- env["rack.input"].read(1)
474
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
475
- }).call(env({"rack.input" => StringIO.new("hello world")}))
476
- }.should.not.raise(Rack::Lint::LintError)
477
-
478
- lambda {
479
- Rack::Lint.new(lambda { |env|
480
- env["rack.input"].read(nil)
481
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
482
- }).call(env({"rack.input" => StringIO.new("hello world")}))
483
- }.should.not.raise(Rack::Lint::LintError)
484
-
485
- lambda {
486
- Rack::Lint.new(lambda { |env|
487
- env["rack.input"].read(nil, '')
488
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
489
- }).call(env({"rack.input" => StringIO.new("hello world")}))
490
- }.should.not.raise(Rack::Lint::LintError)
491
-
492
- lambda {
493
- Rack::Lint.new(lambda { |env|
494
- env["rack.input"].read(1, '')
495
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
496
- }).call(env({"rack.input" => StringIO.new("hello world")}))
497
- }.should.not.raise(Rack::Lint::LintError)
498
- end
499
- end
500
-
501
- context "Rack::Lint::InputWrapper" do
502
- specify "delegates :size to underlying IO object" do
503
- class IOMock
504
- def size
505
- 101
506
- end
507
- end
508
-
509
- wrapper = Rack::Lint::InputWrapper.new(IOMock.new)
510
- wrapper.size.should == 101
511
- end
512
-
513
- specify "delegates :rewind to underlying IO object" do
514
- io = StringIO.new("123")
515
- wrapper = Rack::Lint::InputWrapper.new(io)
516
- wrapper.read.should.equal "123"
517
- wrapper.read.should.equal ""
518
- wrapper.rewind
519
- wrapper.read.should.equal "123"
520
- end
521
- end
@@ -1,45 +0,0 @@
1
- require 'test/spec'
2
-
3
- require 'rack/lobster'
4
- require 'rack/mock'
5
-
6
- context "Rack::Lobster::LambdaLobster" do
7
- specify "should be a single lambda" do
8
- Rack::Lobster::LambdaLobster.should.be.kind_of Proc
9
- end
10
-
11
- specify "should look like a lobster" do
12
- res = Rack::MockRequest.new(Rack::Lobster::LambdaLobster).get("/")
13
- res.should.be.ok
14
- res.body.should.include "(,(,,(,,,("
15
- res.body.should.include "?flip"
16
- end
17
-
18
- specify "should be flippable" do
19
- res = Rack::MockRequest.new(Rack::Lobster::LambdaLobster).get("/?flip")
20
- res.should.be.ok
21
- res.body.should.include "(,,,(,,(,("
22
- end
23
- end
24
-
25
- context "Rack::Lobster" do
26
- specify "should look like a lobster" do
27
- res = Rack::MockRequest.new(Rack::Lobster.new).get("/")
28
- res.should.be.ok
29
- res.body.should.include "(,(,,(,,,("
30
- res.body.should.include "?flip"
31
- res.body.should.include "crash"
32
- end
33
-
34
- specify "should be flippable" do
35
- res = Rack::MockRequest.new(Rack::Lobster.new).get("/?flip=left")
36
- res.should.be.ok
37
- res.body.should.include "(,,,(,,(,("
38
- end
39
-
40
- specify "should provide crashing for testing purposes" do
41
- lambda {
42
- Rack::MockRequest.new(Rack::Lobster.new).get("/?flip=crash")
43
- }.should.raise
44
- end
45
- end
@@ -1,38 +0,0 @@
1
- require 'test/spec'
2
-
3
- require 'rack/mock'
4
- require 'rack/lock'
5
-
6
- context "Rack::Lock" do
7
- class Lock
8
- attr_reader :synchronized
9
-
10
- def initialize
11
- @synchronized = false
12
- end
13
-
14
- def synchronize
15
- @synchronized = true
16
- yield
17
- end
18
- end
19
-
20
- specify "should call synchronize on lock" do
21
- lock = Lock.new
22
- env = Rack::MockRequest.env_for("/")
23
- app = Rack::Lock.new(lambda { |env| }, lock)
24
- lock.synchronized.should.equal false
25
- app.call(env)
26
- lock.synchronized.should.equal true
27
- end
28
-
29
- specify "should set multithread flag to false" do
30
- app = Rack::Lock.new(lambda { |env| env['rack.multithread'] })
31
- app.call(Rack::MockRequest.env_for("/")).should.equal false
32
- end
33
-
34
- specify "should reset original multithread flag when exiting lock" do
35
- app = Rack::Lock.new(lambda { |env| env })
36
- app.call(Rack::MockRequest.env_for("/"))['rack.multithread'].should.equal true
37
- end
38
- end
@@ -1,60 +0,0 @@
1
- require 'test/spec'
2
-
3
- require 'rack/mock'
4
- require 'rack/methodoverride'
5
- require 'stringio'
6
-
7
- context "Rack::MethodOverride" do
8
- specify "should not affect GET requests" do
9
- env = Rack::MockRequest.env_for("/?_method=delete", :method => "GET")
10
- app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
11
- req = app.call(env)
12
-
13
- req.env["REQUEST_METHOD"].should.equal "GET"
14
- end
15
-
16
- specify "_method parameter should modify REQUEST_METHOD for POST requests" do
17
- env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=put")
18
- app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
19
- req = app.call(env)
20
-
21
- req.env["REQUEST_METHOD"].should.equal "PUT"
22
- end
23
-
24
- specify "X-HTTP-Method-Override header should modify REQUEST_METHOD for POST requests" do
25
- env = Rack::MockRequest.env_for("/",
26
- :method => "POST",
27
- "HTTP_X_HTTP_METHOD_OVERRIDE" => "PUT"
28
- )
29
- app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
30
- req = app.call(env)
31
-
32
- req.env["REQUEST_METHOD"].should.equal "PUT"
33
- end
34
-
35
- specify "should not modify REQUEST_METHOD if the method is unknown" do
36
- env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=foo")
37
- app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
38
- req = app.call(env)
39
-
40
- req.env["REQUEST_METHOD"].should.equal "POST"
41
- end
42
-
43
- specify "should not modify REQUEST_METHOD when _method is nil" do
44
- env = Rack::MockRequest.env_for("/", :method => "POST", :input => "foo=bar")
45
- app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
46
- req = app.call(env)
47
-
48
- req.env["REQUEST_METHOD"].should.equal "POST"
49
- end
50
-
51
- specify "should store the original REQUEST_METHOD prior to overriding" do
52
- env = Rack::MockRequest.env_for("/",
53
- :method => "POST",
54
- :input => "_method=options")
55
- app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
56
- req = app.call(env)
57
-
58
- req.env["rack.methodoverride.original_method"].should.equal "POST"
59
- end
60
- end