rack 1.6.13 → 2.1.4.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 (188) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +92 -0
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +105 -141
  5. data/Rakefile +27 -28
  6. data/SPEC +6 -7
  7. data/bin/rackup +1 -0
  8. data/contrib/rack_logo.svg +164 -111
  9. data/example/lobster.ru +2 -0
  10. data/example/protectedlobster.rb +4 -2
  11. data/example/protectedlobster.ru +3 -1
  12. data/lib/rack/auth/abstract/handler.rb +3 -1
  13. data/lib/rack/auth/abstract/request.rb +7 -1
  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 +5 -4
  18. data/lib/rack/auth/digest/request.rb +3 -1
  19. data/lib/rack/body_proxy.rb +11 -9
  20. data/lib/rack/builder.rb +42 -18
  21. data/lib/rack/cascade.rb +6 -5
  22. data/lib/rack/chunked.rb +33 -10
  23. data/lib/rack/{commonlogger.rb → common_logger.rb} +14 -10
  24. data/lib/rack/{conditionalget.rb → conditional_get.rb} +3 -1
  25. data/lib/rack/config.rb +2 -0
  26. data/lib/rack/content_length.rb +5 -3
  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 +33 -53
  30. data/lib/rack/directory.rb +75 -60
  31. data/lib/rack/etag.rb +8 -5
  32. data/lib/rack/events.rb +156 -0
  33. data/lib/rack/file.rb +4 -149
  34. data/lib/rack/files.rb +178 -0
  35. data/lib/rack/handler/cgi.rb +18 -17
  36. data/lib/rack/handler/fastcgi.rb +17 -16
  37. data/lib/rack/handler/lsws.rb +14 -12
  38. data/lib/rack/handler/scgi.rb +22 -19
  39. data/lib/rack/handler/thin.rb +6 -1
  40. data/lib/rack/handler/webrick.rb +28 -28
  41. data/lib/rack/handler.rb +9 -26
  42. data/lib/rack/head.rb +17 -17
  43. data/lib/rack/lint.rb +55 -52
  44. data/lib/rack/lobster.rb +8 -6
  45. data/lib/rack/lock.rb +17 -10
  46. data/lib/rack/logger.rb +4 -2
  47. data/lib/rack/media_type.rb +43 -0
  48. data/lib/rack/{methodoverride.rb → method_override.rb} +10 -8
  49. data/lib/rack/mime.rb +27 -6
  50. data/lib/rack/mock.rb +101 -60
  51. data/lib/rack/multipart/generator.rb +11 -12
  52. data/lib/rack/multipart/parser.rb +292 -161
  53. data/lib/rack/multipart/uploaded_file.rb +3 -2
  54. data/lib/rack/multipart.rb +38 -8
  55. data/lib/rack/{nulllogger.rb → null_logger.rb} +3 -1
  56. data/lib/rack/query_parser.rb +218 -0
  57. data/lib/rack/recursive.rb +11 -9
  58. data/lib/rack/reloader.rb +10 -4
  59. data/lib/rack/request.rb +447 -305
  60. data/lib/rack/response.rb +196 -83
  61. data/lib/rack/rewindable_input.rb +5 -14
  62. data/lib/rack/runtime.rb +12 -18
  63. data/lib/rack/sendfile.rb +19 -14
  64. data/lib/rack/server.rb +118 -41
  65. data/lib/rack/session/abstract/id.rb +139 -94
  66. data/lib/rack/session/cookie.rb +34 -26
  67. data/lib/rack/session/memcache.rb +4 -93
  68. data/lib/rack/session/pool.rb +12 -10
  69. data/lib/rack/show_exceptions.rb +392 -0
  70. data/lib/rack/{showstatus.rb → show_status.rb} +7 -5
  71. data/lib/rack/static.rb +41 -11
  72. data/lib/rack/tempfile_reaper.rb +4 -2
  73. data/lib/rack/urlmap.rb +25 -15
  74. data/lib/rack/utils.rb +203 -277
  75. data/lib/rack.rb +76 -24
  76. data/rack.gemspec +25 -14
  77. metadata +62 -183
  78. data/HISTORY.md +0 -375
  79. data/KNOWN-ISSUES +0 -44
  80. data/lib/rack/backports/uri/common_18.rb +0 -56
  81. data/lib/rack/backports/uri/common_192.rb +0 -52
  82. data/lib/rack/backports/uri/common_193.rb +0 -29
  83. data/lib/rack/handler/evented_mongrel.rb +0 -8
  84. data/lib/rack/handler/mongrel.rb +0 -106
  85. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  86. data/lib/rack/showexceptions.rb +0 -387
  87. data/lib/rack/utils/okjson.rb +0 -600
  88. data/test/builder/anything.rb +0 -5
  89. data/test/builder/comment.ru +0 -4
  90. data/test/builder/end.ru +0 -5
  91. data/test/builder/line.ru +0 -1
  92. data/test/builder/options.ru +0 -2
  93. data/test/cgi/assets/folder/test.js +0 -1
  94. data/test/cgi/assets/fonts/font.eot +0 -1
  95. data/test/cgi/assets/images/image.png +0 -1
  96. data/test/cgi/assets/index.html +0 -1
  97. data/test/cgi/assets/javascripts/app.js +0 -1
  98. data/test/cgi/assets/stylesheets/app.css +0 -1
  99. data/test/cgi/lighttpd.conf +0 -26
  100. data/test/cgi/rackup_stub.rb +0 -6
  101. data/test/cgi/sample_rackup.ru +0 -5
  102. data/test/cgi/test +0 -9
  103. data/test/cgi/test+directory/test+file +0 -1
  104. data/test/cgi/test.fcgi +0 -8
  105. data/test/cgi/test.ru +0 -5
  106. data/test/gemloader.rb +0 -10
  107. data/test/multipart/bad_robots +0 -259
  108. data/test/multipart/binary +0 -0
  109. data/test/multipart/content_type_and_no_filename +0 -6
  110. data/test/multipart/empty +0 -10
  111. data/test/multipart/fail_16384_nofile +0 -814
  112. data/test/multipart/file1.txt +0 -1
  113. data/test/multipart/filename_and_modification_param +0 -7
  114. data/test/multipart/filename_and_no_name +0 -6
  115. data/test/multipart/filename_with_escaped_quotes +0 -6
  116. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  117. data/test/multipart/filename_with_null_byte +0 -7
  118. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  119. data/test/multipart/filename_with_unescaped_percentages +0 -6
  120. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  121. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  122. data/test/multipart/filename_with_unescaped_quotes +0 -6
  123. data/test/multipart/ie +0 -6
  124. data/test/multipart/invalid_character +0 -6
  125. data/test/multipart/mixed_files +0 -21
  126. data/test/multipart/nested +0 -10
  127. data/test/multipart/none +0 -9
  128. data/test/multipart/semicolon +0 -6
  129. data/test/multipart/text +0 -15
  130. data/test/multipart/three_files_three_fields +0 -31
  131. data/test/multipart/webkit +0 -32
  132. data/test/rackup/config.ru +0 -31
  133. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  134. data/test/spec_auth_basic.rb +0 -81
  135. data/test/spec_auth_digest.rb +0 -259
  136. data/test/spec_body_proxy.rb +0 -85
  137. data/test/spec_builder.rb +0 -223
  138. data/test/spec_cascade.rb +0 -61
  139. data/test/spec_cgi.rb +0 -102
  140. data/test/spec_chunked.rb +0 -101
  141. data/test/spec_commonlogger.rb +0 -93
  142. data/test/spec_conditionalget.rb +0 -102
  143. data/test/spec_config.rb +0 -22
  144. data/test/spec_content_length.rb +0 -85
  145. data/test/spec_content_type.rb +0 -45
  146. data/test/spec_deflater.rb +0 -339
  147. data/test/spec_directory.rb +0 -88
  148. data/test/spec_etag.rb +0 -107
  149. data/test/spec_fastcgi.rb +0 -107
  150. data/test/spec_file.rb +0 -221
  151. data/test/spec_handler.rb +0 -72
  152. data/test/spec_head.rb +0 -45
  153. data/test/spec_lint.rb +0 -550
  154. data/test/spec_lobster.rb +0 -58
  155. data/test/spec_lock.rb +0 -164
  156. data/test/spec_logger.rb +0 -23
  157. data/test/spec_methodoverride.rb +0 -111
  158. data/test/spec_mime.rb +0 -51
  159. data/test/spec_mock.rb +0 -297
  160. data/test/spec_mongrel.rb +0 -182
  161. data/test/spec_multipart.rb +0 -600
  162. data/test/spec_nulllogger.rb +0 -20
  163. data/test/spec_recursive.rb +0 -72
  164. data/test/spec_request.rb +0 -1232
  165. data/test/spec_response.rb +0 -407
  166. data/test/spec_rewindable_input.rb +0 -118
  167. data/test/spec_runtime.rb +0 -49
  168. data/test/spec_sendfile.rb +0 -130
  169. data/test/spec_server.rb +0 -167
  170. data/test/spec_session_abstract_id.rb +0 -53
  171. data/test/spec_session_cookie.rb +0 -410
  172. data/test/spec_session_memcache.rb +0 -358
  173. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  174. data/test/spec_session_pool.rb +0 -246
  175. data/test/spec_showexceptions.rb +0 -98
  176. data/test/spec_showstatus.rb +0 -103
  177. data/test/spec_static.rb +0 -145
  178. data/test/spec_tempfile_reaper.rb +0 -63
  179. data/test/spec_thin.rb +0 -91
  180. data/test/spec_urlmap.rb +0 -236
  181. data/test/spec_utils.rb +0 -647
  182. data/test/spec_version.rb +0 -17
  183. data/test/spec_webrick.rb +0 -184
  184. data/test/static/another/index.html +0 -1
  185. data/test/static/index.html +0 -1
  186. data/test/testrequest.rb +0 -78
  187. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  188. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/test/spec_lint.rb DELETED
@@ -1,550 +0,0 @@
1
- require 'stringio'
2
- require 'tempfile'
3
- require 'rack/lint'
4
- require 'rack/mock'
5
-
6
- describe Rack::Lint do
7
- def env(*args)
8
- Rack::MockRequest.env_for("/", *args)
9
- end
10
-
11
- should "pass valid request" do
12
- lambda {
13
- Rack::Lint.new(lambda { |env|
14
- [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]]
15
- }).call(env({}))
16
- }.should.not.raise
17
- end
18
-
19
- should "notice fatal errors" do
20
- lambda { Rack::Lint.new(nil).call }.should.raise(Rack::Lint::LintError).
21
- message.should.match(/No env given/)
22
- end
23
-
24
- should "notice environment errors" do
25
- lambda { Rack::Lint.new(nil).call 5 }.should.raise(Rack::Lint::LintError).
26
- message.should.match(/not a Hash/)
27
-
28
- lambda {
29
- e = env
30
- e.delete("REQUEST_METHOD")
31
- Rack::Lint.new(nil).call(e)
32
- }.should.raise(Rack::Lint::LintError).
33
- message.should.match(/missing required key REQUEST_METHOD/)
34
-
35
- lambda {
36
- e = env
37
- e.delete("SERVER_NAME")
38
- Rack::Lint.new(nil).call(e)
39
- }.should.raise(Rack::Lint::LintError).
40
- message.should.match(/missing required key SERVER_NAME/)
41
-
42
-
43
- lambda {
44
- Rack::Lint.new(nil).call(env("HTTP_CONTENT_TYPE" => "text/plain"))
45
- }.should.raise(Rack::Lint::LintError).
46
- message.should.match(/contains HTTP_CONTENT_TYPE/)
47
-
48
- lambda {
49
- Rack::Lint.new(nil).call(env("HTTP_CONTENT_LENGTH" => "42"))
50
- }.should.raise(Rack::Lint::LintError).
51
- message.should.match(/contains HTTP_CONTENT_LENGTH/)
52
-
53
- lambda {
54
- Rack::Lint.new(nil).call(env("FOO" => Object.new))
55
- }.should.raise(Rack::Lint::LintError).
56
- message.should.match(/non-string value/)
57
-
58
- lambda {
59
- Rack::Lint.new(nil).call(env("rack.version" => "0.2"))
60
- }.should.raise(Rack::Lint::LintError).
61
- message.should.match(/must be an Array/)
62
-
63
- lambda {
64
- Rack::Lint.new(nil).call(env("rack.url_scheme" => "gopher"))
65
- }.should.raise(Rack::Lint::LintError).
66
- message.should.match(/url_scheme unknown/)
67
-
68
- lambda {
69
- Rack::Lint.new(nil).call(env("rack.session" => []))
70
- }.should.raise(Rack::Lint::LintError).
71
- message.should.equal("session [] must respond to store and []=")
72
-
73
- lambda {
74
- Rack::Lint.new(nil).call(env("rack.logger" => []))
75
- }.should.raise(Rack::Lint::LintError).
76
- message.should.equal("logger [] must respond to info")
77
-
78
- lambda {
79
- Rack::Lint.new(nil).call(env("rack.multipart.buffer_size" => 0))
80
- }.should.raise(Rack::Lint::LintError).
81
- message.should.equal("rack.multipart.buffer_size must be an Integer > 0 if specified")
82
-
83
- lambda {
84
- Rack::Lint.new(nil).call(env("rack.multipart.tempfile_factory" => Tempfile))
85
- }.should.raise(Rack::Lint::LintError).
86
- message.should.equal("rack.multipart.tempfile_factory must respond to #call")
87
-
88
- lambda {
89
- Rack::Lint.new(lambda { |env|
90
- env['rack.multipart.tempfile_factory'].call("testfile", "text/plain")
91
- }).call(env("rack.multipart.tempfile_factory" => lambda { |filename, content_type| Object.new }))
92
- }.should.raise(Rack::Lint::LintError).
93
- message.should.equal("rack.multipart.tempfile_factory return value must respond to #<<")
94
-
95
- lambda {
96
- Rack::Lint.new(nil).call(env("REQUEST_METHOD" => "FUCKUP?"))
97
- }.should.raise(Rack::Lint::LintError).
98
- message.should.match(/REQUEST_METHOD/)
99
-
100
- lambda {
101
- Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "howdy"))
102
- }.should.raise(Rack::Lint::LintError).
103
- message.should.match(/must start with/)
104
-
105
- lambda {
106
- Rack::Lint.new(nil).call(env("PATH_INFO" => "../foo"))
107
- }.should.raise(Rack::Lint::LintError).
108
- message.should.match(/must start with/)
109
-
110
- lambda {
111
- Rack::Lint.new(nil).call(env("CONTENT_LENGTH" => "xcii"))
112
- }.should.raise(Rack::Lint::LintError).
113
- message.should.match(/Invalid CONTENT_LENGTH/)
114
-
115
- lambda {
116
- e = env
117
- e.delete("PATH_INFO")
118
- e.delete("SCRIPT_NAME")
119
- Rack::Lint.new(nil).call(e)
120
- }.should.raise(Rack::Lint::LintError).
121
- message.should.match(/One of .* must be set/)
122
-
123
- lambda {
124
- Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "/"))
125
- }.should.raise(Rack::Lint::LintError).
126
- message.should.match(/cannot be .* make it ''/)
127
- end
128
-
129
- should "notice input errors" do
130
- lambda {
131
- Rack::Lint.new(nil).call(env("rack.input" => ""))
132
- }.should.raise(Rack::Lint::LintError).
133
- message.should.match(/does not respond to #gets/)
134
-
135
- lambda {
136
- input = Object.new
137
- def input.binmode?
138
- false
139
- end
140
- Rack::Lint.new(nil).call(env("rack.input" => input))
141
- }.should.raise(Rack::Lint::LintError).
142
- message.should.match(/is not opened in binary mode/)
143
-
144
- lambda {
145
- input = Object.new
146
- def input.external_encoding
147
- result = Object.new
148
- def result.name
149
- "US-ASCII"
150
- end
151
- result
152
- end
153
- Rack::Lint.new(nil).call(env("rack.input" => input))
154
- }.should.raise(Rack::Lint::LintError).
155
- message.should.match(/does not have ASCII-8BIT as its external encoding/)
156
- end
157
-
158
- should "notice error errors" do
159
- lambda {
160
- Rack::Lint.new(nil).call(env("rack.errors" => ""))
161
- }.should.raise(Rack::Lint::LintError).
162
- message.should.match(/does not respond to #puts/)
163
- end
164
-
165
- should "notice status errors" do
166
- lambda {
167
- Rack::Lint.new(lambda { |env|
168
- ["cc", {}, ""]
169
- }).call(env({}))
170
- }.should.raise(Rack::Lint::LintError).
171
- message.should.match(/must be >=100 seen as integer/)
172
-
173
- lambda {
174
- Rack::Lint.new(lambda { |env|
175
- [42, {}, ""]
176
- }).call(env({}))
177
- }.should.raise(Rack::Lint::LintError).
178
- message.should.match(/must be >=100 seen as integer/)
179
- end
180
-
181
- should "notice header errors" do
182
- lambda {
183
- Rack::Lint.new(lambda { |env|
184
- [200, Object.new, []]
185
- }).call(env({}))
186
- }.should.raise(Rack::Lint::LintError).
187
- message.should.equal("headers object should respond to #each, but doesn't (got Object as headers)")
188
-
189
- lambda {
190
- Rack::Lint.new(lambda { |env|
191
- [200, {true=>false}, []]
192
- }).call(env({}))
193
- }.should.raise(Rack::Lint::LintError).
194
- message.should.equal("header key must be a string, was TrueClass")
195
-
196
- lambda {
197
- Rack::Lint.new(lambda { |env|
198
- [200, {"Status" => "404"}, []]
199
- }).call(env({}))
200
- }.should.raise(Rack::Lint::LintError).
201
- message.should.match(/must not contain Status/)
202
-
203
- # From RFC 7230:<F24><F25>
204
- # Most HTTP header field values are defined using common syntax
205
- # components (token, quoted-string, and comment) separated by
206
- # whitespace or specific delimiting characters. Delimiters are chosen
207
- # from the set of US-ASCII visual characters not allowed in a token
208
- # (DQUOTE and "(),/:;<=>?@[\]{}").
209
- #
210
- # token = 1*tchar
211
- #
212
- # tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
213
- # / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
214
- # / DIGIT / ALPHA
215
- # ; any VCHAR, except delimiters
216
- invalid_headers = 0.upto(31).map(&:chr) + %W<( ) , / : ; < = > ? @ [ \\ ] { } \x7F>
217
- invalid_headers.each do |invalid_header|
218
- lambda {
219
- Rack::Lint.new(lambda { |env|
220
- [200, {invalid_header => "text/plain"}, []]
221
- }).call(env({}))
222
- }.should.raise(Rack::Lint::LintError, "on invalid header: #{invalid_header}").
223
- message.should.equal("invalid header name: #{invalid_header}")
224
- end
225
- valid_headers = 0.upto(127).map(&:chr) - invalid_headers
226
- valid_headers.each do |valid_header|
227
- lambda {
228
- Rack::Lint.new(lambda { |env|
229
- [200, {valid_header => "text/plain"}, []]
230
- }).call(env({}))
231
- }.should.not.raise(Rack::Lint::LintError, "on valid header: #{valid_header}")
232
- end
233
-
234
- lambda {
235
- Rack::Lint.new(lambda { |env|
236
- [200, {"Foo" => Object.new}, []]
237
- }).call(env({}))
238
- }.should.raise(Rack::Lint::LintError).
239
- message.should.equal("a header value must be a String, but the value of 'Foo' is a Object")
240
-
241
- lambda {
242
- Rack::Lint.new(lambda { |env|
243
- [200, {"Foo" => [1, 2, 3]}, []]
244
- }).call(env({}))
245
- }.should.raise(Rack::Lint::LintError).
246
- message.should.equal("a header value must be a String, but the value of 'Foo' is a Array")
247
-
248
-
249
- lambda {
250
- Rack::Lint.new(lambda { |env|
251
- [200, {"Foo-Bar" => "text\000plain"}, []]
252
- }).call(env({}))
253
- }.should.raise(Rack::Lint::LintError).
254
- message.should.match(/invalid header/)
255
-
256
- # line ends (010) should be allowed in header values.
257
- lambda {
258
- Rack::Lint.new(lambda { |env|
259
- [200, {"Foo-Bar" => "one\ntwo\nthree", "Content-Length" => "0", "Content-Type" => "text/plain" }, []]
260
- }).call(env({}))
261
- }.should.not.raise(Rack::Lint::LintError)
262
-
263
- # non-Hash header responses should be allowed
264
- lambda {
265
- Rack::Lint.new(lambda { |env|
266
- [200, [%w(Content-Type text/plain), %w(Content-Length 0)], []]
267
- }).call(env({}))
268
- }.should.not.raise(TypeError)
269
- end
270
-
271
- should "notice content-type errors" do
272
- # lambda {
273
- # Rack::Lint.new(lambda { |env|
274
- # [200, {"Content-length" => "0"}, []]
275
- # }).call(env({}))
276
- # }.should.raise(Rack::Lint::LintError).
277
- # message.should.match(/No Content-Type/)
278
-
279
- [100, 101, 204, 205, 304].each do |status|
280
- lambda {
281
- Rack::Lint.new(lambda { |env|
282
- [status, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
283
- }).call(env({}))
284
- }.should.raise(Rack::Lint::LintError).
285
- message.should.match(/Content-Type header found/)
286
- end
287
- end
288
-
289
- should "notice content-length errors" do
290
- [100, 101, 204, 205, 304].each do |status|
291
- lambda {
292
- Rack::Lint.new(lambda { |env|
293
- [status, {"Content-length" => "0"}, []]
294
- }).call(env({}))
295
- }.should.raise(Rack::Lint::LintError).
296
- message.should.match(/Content-Length header found/)
297
- end
298
-
299
- lambda {
300
- Rack::Lint.new(lambda { |env|
301
- [200, {"Content-type" => "text/plain", "Content-Length" => "1"}, []]
302
- }).call(env({}))[2].each { }
303
- }.should.raise(Rack::Lint::LintError).
304
- message.should.match(/Content-Length header was 1, but should be 0/)
305
- end
306
-
307
- should "notice body errors" do
308
- lambda {
309
- body = Rack::Lint.new(lambda { |env|
310
- [200, {"Content-type" => "text/plain","Content-length" => "3"}, [1,2,3]]
311
- }).call(env({}))[2]
312
- body.each { |part| }
313
- }.should.raise(Rack::Lint::LintError).
314
- message.should.match(/yielded non-string/)
315
- end
316
-
317
- should "notice input handling errors" do
318
- lambda {
319
- Rack::Lint.new(lambda { |env|
320
- env["rack.input"].gets("\r\n")
321
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
322
- }).call(env({}))
323
- }.should.raise(Rack::Lint::LintError).
324
- message.should.match(/gets called with arguments/)
325
-
326
- lambda {
327
- Rack::Lint.new(lambda { |env|
328
- env["rack.input"].read(1, 2, 3)
329
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
330
- }).call(env({}))
331
- }.should.raise(Rack::Lint::LintError).
332
- message.should.match(/read called with too many arguments/)
333
-
334
- lambda {
335
- Rack::Lint.new(lambda { |env|
336
- env["rack.input"].read("foo")
337
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
338
- }).call(env({}))
339
- }.should.raise(Rack::Lint::LintError).
340
- message.should.match(/read called with non-integer and non-nil length/)
341
-
342
- lambda {
343
- Rack::Lint.new(lambda { |env|
344
- env["rack.input"].read(-1)
345
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
346
- }).call(env({}))
347
- }.should.raise(Rack::Lint::LintError).
348
- message.should.match(/read called with a negative length/)
349
-
350
- lambda {
351
- Rack::Lint.new(lambda { |env|
352
- env["rack.input"].read(nil, nil)
353
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
354
- }).call(env({}))
355
- }.should.raise(Rack::Lint::LintError).
356
- message.should.match(/read called with non-String buffer/)
357
-
358
- lambda {
359
- Rack::Lint.new(lambda { |env|
360
- env["rack.input"].read(nil, 1)
361
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
362
- }).call(env({}))
363
- }.should.raise(Rack::Lint::LintError).
364
- message.should.match(/read called with non-String buffer/)
365
-
366
- lambda {
367
- Rack::Lint.new(lambda { |env|
368
- env["rack.input"].rewind(0)
369
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
370
- }).call(env({}))
371
- }.should.raise(Rack::Lint::LintError).
372
- message.should.match(/rewind called with arguments/)
373
-
374
- weirdio = Object.new
375
- class << weirdio
376
- def gets
377
- 42
378
- end
379
-
380
- def read
381
- 23
382
- end
383
-
384
- def each
385
- yield 23
386
- yield 42
387
- end
388
-
389
- def rewind
390
- raise Errno::ESPIPE, "Errno::ESPIPE"
391
- end
392
- end
393
-
394
- eof_weirdio = Object.new
395
- class << eof_weirdio
396
- def gets
397
- nil
398
- end
399
-
400
- def read(*args)
401
- nil
402
- end
403
-
404
- def each
405
- end
406
-
407
- def rewind
408
- end
409
- end
410
-
411
- lambda {
412
- Rack::Lint.new(lambda { |env|
413
- env["rack.input"].gets
414
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
415
- }).call(env("rack.input" => weirdio))
416
- }.should.raise(Rack::Lint::LintError).
417
- message.should.match(/gets didn't return a String/)
418
-
419
- lambda {
420
- Rack::Lint.new(lambda { |env|
421
- env["rack.input"].each { |x| }
422
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
423
- }).call(env("rack.input" => weirdio))
424
- }.should.raise(Rack::Lint::LintError).
425
- message.should.match(/each didn't yield a String/)
426
-
427
- lambda {
428
- Rack::Lint.new(lambda { |env|
429
- env["rack.input"].read
430
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
431
- }).call(env("rack.input" => weirdio))
432
- }.should.raise(Rack::Lint::LintError).
433
- message.should.match(/read didn't return nil or a String/)
434
-
435
- lambda {
436
- Rack::Lint.new(lambda { |env|
437
- env["rack.input"].read
438
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
439
- }).call(env("rack.input" => eof_weirdio))
440
- }.should.raise(Rack::Lint::LintError).
441
- message.should.match(/read\(nil\) returned nil on EOF/)
442
-
443
- lambda {
444
- Rack::Lint.new(lambda { |env|
445
- env["rack.input"].rewind
446
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
447
- }).call(env("rack.input" => weirdio))
448
- }.should.raise(Rack::Lint::LintError).
449
- message.should.match(/rewind raised Errno::ESPIPE/)
450
-
451
-
452
- lambda {
453
- Rack::Lint.new(lambda { |env|
454
- env["rack.input"].close
455
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
456
- }).call(env({}))
457
- }.should.raise(Rack::Lint::LintError).
458
- message.should.match(/close must not be called/)
459
- end
460
-
461
- should "notice error handling errors" do
462
- lambda {
463
- Rack::Lint.new(lambda { |env|
464
- env["rack.errors"].write(42)
465
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
466
- }).call(env({}))
467
- }.should.raise(Rack::Lint::LintError).
468
- message.should.match(/write not called with a String/)
469
-
470
- lambda {
471
- Rack::Lint.new(lambda { |env|
472
- env["rack.errors"].close
473
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
474
- }).call(env({}))
475
- }.should.raise(Rack::Lint::LintError).
476
- message.should.match(/close must not be called/)
477
- end
478
-
479
- should "notice HEAD errors" do
480
- lambda {
481
- Rack::Lint.new(lambda { |env|
482
- [200, {"Content-type" => "test/plain", "Content-length" => "3"}, []]
483
- }).call(env({"REQUEST_METHOD" => "HEAD"}))
484
- }.should.not.raise
485
-
486
- lambda {
487
- Rack::Lint.new(lambda { |env|
488
- [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]]
489
- }).call(env({"REQUEST_METHOD" => "HEAD"}))[2].each { }
490
- }.should.raise(Rack::Lint::LintError).
491
- message.should.match(/body was given for HEAD/)
492
- end
493
-
494
- should "pass valid read calls" do
495
- hello_str = "hello world"
496
- hello_str.force_encoding("ASCII-8BIT") if hello_str.respond_to? :force_encoding
497
- lambda {
498
- Rack::Lint.new(lambda { |env|
499
- env["rack.input"].read
500
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
501
- }).call(env({"rack.input" => StringIO.new(hello_str)}))
502
- }.should.not.raise(Rack::Lint::LintError)
503
-
504
- lambda {
505
- Rack::Lint.new(lambda { |env|
506
- env["rack.input"].read(0)
507
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
508
- }).call(env({"rack.input" => StringIO.new(hello_str)}))
509
- }.should.not.raise(Rack::Lint::LintError)
510
-
511
- lambda {
512
- Rack::Lint.new(lambda { |env|
513
- env["rack.input"].read(1)
514
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
515
- }).call(env({"rack.input" => StringIO.new(hello_str)}))
516
- }.should.not.raise(Rack::Lint::LintError)
517
-
518
- lambda {
519
- Rack::Lint.new(lambda { |env|
520
- env["rack.input"].read(nil)
521
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
522
- }).call(env({"rack.input" => StringIO.new(hello_str)}))
523
- }.should.not.raise(Rack::Lint::LintError)
524
-
525
- lambda {
526
- Rack::Lint.new(lambda { |env|
527
- env["rack.input"].read(nil, '')
528
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
529
- }).call(env({"rack.input" => StringIO.new(hello_str)}))
530
- }.should.not.raise(Rack::Lint::LintError)
531
-
532
- lambda {
533
- Rack::Lint.new(lambda { |env|
534
- env["rack.input"].read(1, '')
535
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
536
- }).call(env({"rack.input" => StringIO.new(hello_str)}))
537
- }.should.not.raise(Rack::Lint::LintError)
538
- end
539
- end
540
-
541
- describe "Rack::Lint::InputWrapper" do
542
- should "delegate :rewind to underlying IO object" do
543
- io = StringIO.new("123")
544
- wrapper = Rack::Lint::InputWrapper.new(io)
545
- wrapper.read.should.equal "123"
546
- wrapper.read.should.equal ""
547
- wrapper.rewind
548
- wrapper.read.should.equal "123"
549
- end
550
- end
data/test/spec_lobster.rb DELETED
@@ -1,58 +0,0 @@
1
- require 'rack/lobster'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
-
5
- module LobsterHelpers
6
- def lobster
7
- Rack::MockRequest.new Rack::Lint.new(Rack::Lobster.new)
8
- end
9
-
10
- def lambda_lobster
11
- Rack::MockRequest.new Rack::Lint.new(Rack::Lobster::LambdaLobster)
12
- end
13
- end
14
-
15
- describe Rack::Lobster::LambdaLobster do
16
- extend LobsterHelpers
17
-
18
- should "be a single lambda" do
19
- Rack::Lobster::LambdaLobster.should.be.kind_of Proc
20
- end
21
-
22
- should "look like a lobster" do
23
- res = lambda_lobster.get("/")
24
- res.should.be.ok
25
- res.body.should.include "(,(,,(,,,("
26
- res.body.should.include "?flip"
27
- end
28
-
29
- should "be flippable" do
30
- res = lambda_lobster.get("/?flip")
31
- res.should.be.ok
32
- res.body.should.include "(,,,(,,(,("
33
- end
34
- end
35
-
36
- describe Rack::Lobster do
37
- extend LobsterHelpers
38
-
39
- should "look like a lobster" do
40
- res = lobster.get("/")
41
- res.should.be.ok
42
- res.body.should.include "(,(,,(,,,("
43
- res.body.should.include "?flip"
44
- res.body.should.include "crash"
45
- end
46
-
47
- should "be flippable" do
48
- res = lobster.get("/?flip=left")
49
- res.should.be.ok
50
- res.body.should.include "),,,),,),)"
51
- end
52
-
53
- should "provide crashing for testing purposes" do
54
- lambda {
55
- lobster.get("/?flip=crash")
56
- }.should.raise
57
- end
58
- end