qoobaa-rack 1.0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/COPYING +18 -0
  2. data/KNOWN-ISSUES +18 -0
  3. data/RDOX +0 -0
  4. data/README +353 -0
  5. data/Rakefile +164 -0
  6. data/SPEC +164 -0
  7. data/bin/rackup +176 -0
  8. data/contrib/rack_logo.svg +111 -0
  9. data/example/lobster.ru +4 -0
  10. data/example/protectedlobster.rb +14 -0
  11. data/example/protectedlobster.ru +8 -0
  12. data/lib/rack/adapter/camping.rb +22 -0
  13. data/lib/rack/auth/abstract/handler.rb +37 -0
  14. data/lib/rack/auth/abstract/request.rb +37 -0
  15. data/lib/rack/auth/basic.rb +58 -0
  16. data/lib/rack/auth/digest/md5.rb +124 -0
  17. data/lib/rack/auth/digest/nonce.rb +51 -0
  18. data/lib/rack/auth/digest/params.rb +55 -0
  19. data/lib/rack/auth/digest/request.rb +40 -0
  20. data/lib/rack/auth/openid.rb +487 -0
  21. data/lib/rack/builder.rb +63 -0
  22. data/lib/rack/cascade.rb +41 -0
  23. data/lib/rack/chunked.rb +49 -0
  24. data/lib/rack/commonlogger.rb +52 -0
  25. data/lib/rack/conditionalget.rb +47 -0
  26. data/lib/rack/content_length.rb +29 -0
  27. data/lib/rack/content_type.rb +23 -0
  28. data/lib/rack/deflater.rb +96 -0
  29. data/lib/rack/directory.rb +153 -0
  30. data/lib/rack/file.rb +88 -0
  31. data/lib/rack/handler/cgi.rb +61 -0
  32. data/lib/rack/handler/evented_mongrel.rb +8 -0
  33. data/lib/rack/handler/fastcgi.rb +88 -0
  34. data/lib/rack/handler/lsws.rb +60 -0
  35. data/lib/rack/handler/mongrel.rb +87 -0
  36. data/lib/rack/handler/scgi.rb +62 -0
  37. data/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
  38. data/lib/rack/handler/thin.rb +18 -0
  39. data/lib/rack/handler/webrick.rb +71 -0
  40. data/lib/rack/handler.rb +69 -0
  41. data/lib/rack/head.rb +19 -0
  42. data/lib/rack/lint.rb +546 -0
  43. data/lib/rack/lobster.rb +65 -0
  44. data/lib/rack/lock.rb +16 -0
  45. data/lib/rack/methodoverride.rb +27 -0
  46. data/lib/rack/mime.rb +204 -0
  47. data/lib/rack/mock.rb +187 -0
  48. data/lib/rack/recursive.rb +57 -0
  49. data/lib/rack/reloader.rb +107 -0
  50. data/lib/rack/request.rb +248 -0
  51. data/lib/rack/response.rb +183 -0
  52. data/lib/rack/rewindable_input.rb +100 -0
  53. data/lib/rack/session/abstract/id.rb +142 -0
  54. data/lib/rack/session/cookie.rb +91 -0
  55. data/lib/rack/session/memcache.rb +109 -0
  56. data/lib/rack/session/pool.rb +100 -0
  57. data/lib/rack/showexceptions.rb +349 -0
  58. data/lib/rack/showstatus.rb +106 -0
  59. data/lib/rack/static.rb +38 -0
  60. data/lib/rack/urlmap.rb +55 -0
  61. data/lib/rack/utils.rb +528 -0
  62. data/lib/rack.rb +90 -0
  63. data/rack.gemspec +60 -0
  64. data/test/cgi/lighttpd.conf +20 -0
  65. data/test/cgi/test +9 -0
  66. data/test/cgi/test.fcgi +8 -0
  67. data/test/cgi/test.ru +7 -0
  68. data/test/multipart/binary +0 -0
  69. data/test/multipart/empty +10 -0
  70. data/test/multipart/file1.txt +1 -0
  71. data/test/multipart/ie +6 -0
  72. data/test/multipart/nested +10 -0
  73. data/test/multipart/none +9 -0
  74. data/test/multipart/text +10 -0
  75. data/test/spec_rack_auth_basic.rb +73 -0
  76. data/test/spec_rack_auth_digest.rb +226 -0
  77. data/test/spec_rack_auth_openid.rb +84 -0
  78. data/test/spec_rack_builder.rb +84 -0
  79. data/test/spec_rack_camping.rb +51 -0
  80. data/test/spec_rack_cascade.rb +48 -0
  81. data/test/spec_rack_cgi.rb +89 -0
  82. data/test/spec_rack_chunked.rb +62 -0
  83. data/test/spec_rack_commonlogger.rb +61 -0
  84. data/test/spec_rack_conditionalget.rb +41 -0
  85. data/test/spec_rack_content_length.rb +43 -0
  86. data/test/spec_rack_content_type.rb +30 -0
  87. data/test/spec_rack_deflater.rb +127 -0
  88. data/test/spec_rack_directory.rb +61 -0
  89. data/test/spec_rack_fastcgi.rb +89 -0
  90. data/test/spec_rack_file.rb +75 -0
  91. data/test/spec_rack_handler.rb +43 -0
  92. data/test/spec_rack_head.rb +30 -0
  93. data/test/spec_rack_lint.rb +521 -0
  94. data/test/spec_rack_lobster.rb +45 -0
  95. data/test/spec_rack_lock.rb +38 -0
  96. data/test/spec_rack_methodoverride.rb +60 -0
  97. data/test/spec_rack_mock.rb +243 -0
  98. data/test/spec_rack_mongrel.rb +189 -0
  99. data/test/spec_rack_recursive.rb +77 -0
  100. data/test/spec_rack_request.rb +504 -0
  101. data/test/spec_rack_response.rb +218 -0
  102. data/test/spec_rack_rewindable_input.rb +118 -0
  103. data/test/spec_rack_session_cookie.rb +82 -0
  104. data/test/spec_rack_session_memcache.rb +250 -0
  105. data/test/spec_rack_session_pool.rb +172 -0
  106. data/test/spec_rack_showexceptions.rb +21 -0
  107. data/test/spec_rack_showstatus.rb +72 -0
  108. data/test/spec_rack_static.rb +37 -0
  109. data/test/spec_rack_thin.rb +91 -0
  110. data/test/spec_rack_urlmap.rb +185 -0
  111. data/test/spec_rack_utils.rb +467 -0
  112. data/test/spec_rack_webrick.rb +130 -0
  113. data/test/testrequest.rb +57 -0
  114. data/test/unregistered_handler/rack/handler/unregistered.rb +7 -0
  115. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
  116. metadata +276 -0
@@ -0,0 +1,504 @@
1
+ require 'test/spec'
2
+ require 'stringio'
3
+
4
+ require 'rack/request'
5
+ require 'rack/mock'
6
+
7
+ context "Rack::Request" do
8
+ specify "wraps the rack variables" do
9
+ req = Rack::Request.new(Rack::MockRequest.env_for("http://example.com:8080/"))
10
+
11
+ req.body.should.respond_to? :gets
12
+ req.scheme.should.equal "http"
13
+ req.request_method.should.equal "GET"
14
+
15
+ req.should.be.get
16
+ req.should.not.be.post
17
+ req.should.not.be.put
18
+ req.should.not.be.delete
19
+ req.should.not.be.head
20
+
21
+ req.script_name.should.equal ""
22
+ req.path_info.should.equal "/"
23
+ req.query_string.should.equal ""
24
+
25
+ req.host.should.equal "example.com"
26
+ req.port.should.equal 8080
27
+
28
+ req.content_length.should.equal "0"
29
+ req.content_type.should.be.nil
30
+ end
31
+
32
+ specify "can figure out the correct host" do
33
+ req = Rack::Request.new \
34
+ Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
35
+ req.host.should.equal "www2.example.org"
36
+
37
+ req = Rack::Request.new \
38
+ Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org:9292")
39
+ req.host.should.equal "example.org"
40
+ end
41
+
42
+ specify "can parse the query string" do
43
+ req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
44
+ req.query_string.should.equal "foo=bar&quux=bla"
45
+ req.GET.should.equal "foo" => "bar", "quux" => "bla"
46
+ req.POST.should.be.empty
47
+ req.params.should.equal "foo" => "bar", "quux" => "bla"
48
+ end
49
+
50
+ specify "raises if rack.input is missing" do
51
+ req = Rack::Request.new({})
52
+ lambda { req.POST }.should.raise(RuntimeError)
53
+ end
54
+
55
+ specify "can parse POST data" do
56
+ req = Rack::Request.new \
57
+ Rack::MockRequest.env_for("/?foo=quux", :input => "foo=bar&quux=bla")
58
+ req.content_type.should.be.nil
59
+ req.media_type.should.be.nil
60
+ req.query_string.should.equal "foo=quux"
61
+ req.GET.should.equal "foo" => "quux"
62
+ req.POST.should.equal "foo" => "bar", "quux" => "bla"
63
+ req.params.should.equal "foo" => "bar", "quux" => "bla"
64
+ end
65
+
66
+ specify "can parse POST data with explicit content type" do
67
+ req = Rack::Request.new \
68
+ Rack::MockRequest.env_for("/",
69
+ "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
70
+ :input => "foo=bar&quux=bla")
71
+ req.content_type.should.equal 'application/x-www-form-urlencoded;foo=bar'
72
+ req.media_type.should.equal 'application/x-www-form-urlencoded'
73
+ req.media_type_params['foo'].should.equal 'bar'
74
+ req.POST.should.equal "foo" => "bar", "quux" => "bla"
75
+ req.params.should.equal "foo" => "bar", "quux" => "bla"
76
+ end
77
+
78
+ specify "does not parse POST data when media type is not form-data" do
79
+ req = Rack::Request.new \
80
+ Rack::MockRequest.env_for("/?foo=quux",
81
+ "CONTENT_TYPE" => 'text/plain;charset=utf-8',
82
+ :input => "foo=bar&quux=bla")
83
+ req.content_type.should.equal 'text/plain;charset=utf-8'
84
+ req.media_type.should.equal 'text/plain'
85
+ req.media_type_params['charset'].should.equal 'utf-8'
86
+ req.POST.should.be.empty
87
+ req.params.should.equal "foo" => "quux"
88
+ req.body.read.should.equal "foo=bar&quux=bla"
89
+ end
90
+
91
+ specify "rewinds input after parsing POST data" do
92
+ input = StringIO.new("foo=bar&quux=bla")
93
+ req = Rack::Request.new \
94
+ Rack::MockRequest.env_for("/",
95
+ "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
96
+ :input => input)
97
+ req.params.should.equal "foo" => "bar", "quux" => "bla"
98
+ input.read.should.equal "foo=bar&quux=bla"
99
+ end
100
+
101
+ specify "cleans up Safari's ajax POST body" do
102
+ req = Rack::Request.new \
103
+ Rack::MockRequest.env_for("/", :input => "foo=bar&quux=bla\0")
104
+ req.POST.should.equal "foo" => "bar", "quux" => "bla"
105
+ end
106
+
107
+ specify "can get value by key from params with #[]" do
108
+ req = Rack::Request.new \
109
+ Rack::MockRequest.env_for("?foo=quux")
110
+ req['foo'].should.equal 'quux'
111
+ req[:foo].should.equal 'quux'
112
+ end
113
+
114
+ specify "can set value to key on params with #[]=" do
115
+ req = Rack::Request.new \
116
+ Rack::MockRequest.env_for("?foo=duh")
117
+ req['foo'].should.equal 'duh'
118
+ req[:foo].should.equal 'duh'
119
+ req.params.should.equal 'foo' => 'duh'
120
+
121
+ req['foo'] = 'bar'
122
+ req.params.should.equal 'foo' => 'bar'
123
+ req['foo'].should.equal 'bar'
124
+ req[:foo].should.equal 'bar'
125
+
126
+ req[:foo] = 'jaz'
127
+ req.params.should.equal 'foo' => 'jaz'
128
+ req['foo'].should.equal 'jaz'
129
+ req[:foo].should.equal 'jaz'
130
+ end
131
+
132
+ specify "values_at answers values by keys in order given" do
133
+ req = Rack::Request.new \
134
+ Rack::MockRequest.env_for("?foo=baz&wun=der&bar=ful")
135
+ req.values_at('foo').should.equal ['baz']
136
+ req.values_at('foo', 'wun').should.equal ['baz', 'der']
137
+ req.values_at('bar', 'foo', 'wun').should.equal ['ful', 'baz', 'der']
138
+ end
139
+
140
+ specify "referrer should be extracted correct" do
141
+ req = Rack::Request.new \
142
+ Rack::MockRequest.env_for("/", "HTTP_REFERER" => "/some/path")
143
+ req.referer.should.equal "/some/path"
144
+
145
+ req = Rack::Request.new \
146
+ Rack::MockRequest.env_for("/")
147
+ req.referer.should.equal "/"
148
+ end
149
+
150
+ specify "can cache, but invalidates the cache" do
151
+ req = Rack::Request.new \
152
+ Rack::MockRequest.env_for("/?foo=quux", :input => "foo=bar&quux=bla")
153
+ req.GET.should.equal "foo" => "quux"
154
+ req.GET.should.equal "foo" => "quux"
155
+ req.env["QUERY_STRING"] = "bla=foo"
156
+ req.GET.should.equal "bla" => "foo"
157
+ req.GET.should.equal "bla" => "foo"
158
+
159
+ req.POST.should.equal "foo" => "bar", "quux" => "bla"
160
+ req.POST.should.equal "foo" => "bar", "quux" => "bla"
161
+ req.env["rack.input"] = StringIO.new("foo=bla&quux=bar")
162
+ req.POST.should.equal "foo" => "bla", "quux" => "bar"
163
+ req.POST.should.equal "foo" => "bla", "quux" => "bar"
164
+ end
165
+
166
+ specify "can figure out if called via XHR" do
167
+ req = Rack::Request.new(Rack::MockRequest.env_for(""))
168
+ req.should.not.be.xhr
169
+
170
+ req = Rack::Request.new \
171
+ Rack::MockRequest.env_for("", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest")
172
+ req.should.be.xhr
173
+ end
174
+
175
+ specify "can parse cookies" do
176
+ req = Rack::Request.new \
177
+ Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
178
+ req.cookies.should.equal "foo" => "bar", "quux" => "h&m"
179
+ req.cookies.should.equal "foo" => "bar", "quux" => "h&m"
180
+ req.env.delete("HTTP_COOKIE")
181
+ req.cookies.should.equal({})
182
+ end
183
+
184
+ specify "parses cookies according to RFC 2109" do
185
+ req = Rack::Request.new \
186
+ Rack::MockRequest.env_for('', 'HTTP_COOKIE' => 'foo=bar;foo=car')
187
+ req.cookies.should.equal 'foo' => 'bar'
188
+ end
189
+
190
+ specify "provides setters" do
191
+ req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
192
+ req.script_name.should.equal ""
193
+ req.script_name = "/foo"
194
+ req.script_name.should.equal "/foo"
195
+ e["SCRIPT_NAME"].should.equal "/foo"
196
+
197
+ req.path_info.should.equal "/"
198
+ req.path_info = "/foo"
199
+ req.path_info.should.equal "/foo"
200
+ e["PATH_INFO"].should.equal "/foo"
201
+ end
202
+
203
+ specify "provides the original env" do
204
+ req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
205
+ req.env.should.be e
206
+ end
207
+
208
+ specify "can restore the URL" do
209
+ Rack::Request.new(Rack::MockRequest.env_for("")).url.
210
+ should.equal "http://example.org/"
211
+ Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).url.
212
+ should.equal "http://example.org/foo/"
213
+ Rack::Request.new(Rack::MockRequest.env_for("/foo")).url.
214
+ should.equal "http://example.org/foo"
215
+ Rack::Request.new(Rack::MockRequest.env_for("?foo")).url.
216
+ should.equal "http://example.org/?foo"
217
+ Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).url.
218
+ should.equal "http://example.org:8080/"
219
+ Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).url.
220
+ should.equal "https://example.org/"
221
+
222
+ Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).url.
223
+ should.equal "https://example.com:8080/foo?foo"
224
+ end
225
+
226
+ specify "can restore the full path" do
227
+ Rack::Request.new(Rack::MockRequest.env_for("")).fullpath.
228
+ should.equal "/"
229
+ Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).fullpath.
230
+ should.equal "/foo/"
231
+ Rack::Request.new(Rack::MockRequest.env_for("/foo")).fullpath.
232
+ should.equal "/foo"
233
+ Rack::Request.new(Rack::MockRequest.env_for("?foo")).fullpath.
234
+ should.equal "/?foo"
235
+ Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).fullpath.
236
+ should.equal "/"
237
+ Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).fullpath.
238
+ should.equal "/"
239
+
240
+ Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).fullpath.
241
+ should.equal "/foo?foo"
242
+ end
243
+
244
+ specify "can handle multiple media type parameters" do
245
+ req = Rack::Request.new \
246
+ Rack::MockRequest.env_for("/",
247
+ "CONTENT_TYPE" => 'text/plain; foo=BAR,baz=bizzle dizzle;BLING=bam')
248
+ req.should.not.be.form_data
249
+ req.media_type_params.should.include 'foo'
250
+ req.media_type_params['foo'].should.equal 'BAR'
251
+ req.media_type_params.should.include 'baz'
252
+ req.media_type_params['baz'].should.equal 'bizzle dizzle'
253
+ req.media_type_params.should.not.include 'BLING'
254
+ req.media_type_params.should.include 'bling'
255
+ req.media_type_params['bling'].should.equal 'bam'
256
+ end
257
+
258
+ specify "can parse multipart form data" do
259
+ # Adapted from RFC 1867.
260
+ input = <<EOF
261
+ --AaB03x\r
262
+ content-disposition: form-data; name="reply"\r
263
+ \r
264
+ yes\r
265
+ --AaB03x\r
266
+ content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
267
+ Content-Type: image/jpeg\r
268
+ Content-Transfer-Encoding: base64\r
269
+ \r
270
+ /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
271
+ --AaB03x--\r
272
+ EOF
273
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
274
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
275
+ "CONTENT_LENGTH" => input.size,
276
+ :input => input)
277
+
278
+ req.POST.should.include "fileupload"
279
+ req.POST.should.include "reply"
280
+
281
+ req.should.be.form_data
282
+ req.content_length.should.equal input.size
283
+ req.media_type.should.equal 'multipart/form-data'
284
+ req.media_type_params.should.include 'boundary'
285
+ req.media_type_params['boundary'].should.equal 'AaB03x'
286
+
287
+ req.POST["reply"].should.equal "yes"
288
+
289
+ f = req.POST["fileupload"]
290
+ f.should.be.kind_of Hash
291
+ f[:type].should.equal "image/jpeg"
292
+ f[:filename].should.equal "dj.jpg"
293
+ f.should.include :tempfile
294
+ f[:tempfile].size.should.equal 76
295
+ end
296
+
297
+ specify "can parse big multipart form data" do
298
+ input = <<EOF
299
+ --AaB03x\r
300
+ content-disposition: form-data; name="huge"; filename="huge"\r
301
+ \r
302
+ #{"x"*32768}\r
303
+ --AaB03x\r
304
+ content-disposition: form-data; name="mean"; filename="mean"\r
305
+ \r
306
+ --AaB03xha\r
307
+ --AaB03x--\r
308
+ EOF
309
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
310
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
311
+ "CONTENT_LENGTH" => input.size,
312
+ :input => input)
313
+
314
+ req.POST["huge"][:tempfile].size.should.equal 32768
315
+ req.POST["mean"][:tempfile].size.should.equal 10
316
+ req.POST["mean"][:tempfile].read.should.equal "--AaB03xha"
317
+ end
318
+
319
+ specify "can detect invalid multipart form data" do
320
+ input = <<EOF
321
+ --AaB03x\r
322
+ content-disposition: form-data; name="huge"; filename="huge"\r
323
+ EOF
324
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
325
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
326
+ "CONTENT_LENGTH" => input.size,
327
+ :input => input)
328
+
329
+ lambda { req.POST }.should.raise(EOFError)
330
+
331
+ input = <<EOF
332
+ --AaB03x\r
333
+ content-disposition: form-data; name="huge"; filename="huge"\r
334
+ \r
335
+ foo\r
336
+ EOF
337
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
338
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
339
+ "CONTENT_LENGTH" => input.size,
340
+ :input => input)
341
+
342
+ lambda { req.POST }.should.raise(EOFError)
343
+
344
+ input = <<EOF
345
+ --AaB03x\r
346
+ content-disposition: form-data; name="huge"; filename="huge"\r
347
+ \r
348
+ foo\r
349
+ EOF
350
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
351
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
352
+ "CONTENT_LENGTH" => input.size,
353
+ :input => input)
354
+
355
+ lambda { req.POST }.should.raise(EOFError)
356
+ end
357
+
358
+ specify "shouldn't try to interpret binary as utf8" do
359
+ begin
360
+ original_kcode = $KCODE
361
+ $KCODE='UTF8'
362
+
363
+ input = <<EOF
364
+ --AaB03x\r
365
+ content-disposition: form-data; name="fileupload"; filename="junk.a"\r
366
+ content-type: application/octet-stream\r
367
+ \r
368
+ #{[0x36,0xCF,0x0A,0xF8].pack('c*')}\r
369
+ --AaB03x--\r
370
+ EOF
371
+
372
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
373
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
374
+ "CONTENT_LENGTH" => input.size,
375
+ :input => input)
376
+
377
+ lambda{req.POST}.should.not.raise(EOFError)
378
+ req.POST["fileupload"][:tempfile].size.should.equal 4
379
+ ensure
380
+ $KCODE = original_kcode
381
+ end
382
+ end
383
+
384
+
385
+ specify "should work around buggy 1.8.* Tempfile equality" do
386
+ input = <<EOF
387
+ --AaB03x\r
388
+ content-disposition: form-data; name="huge"; filename="huge"\r
389
+ \r
390
+ foo\r
391
+ --AaB03x--
392
+ EOF
393
+
394
+ rack_input = Tempfile.new("rackspec")
395
+ rack_input.write(input)
396
+ rack_input.rewind
397
+
398
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
399
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
400
+ "CONTENT_LENGTH" => input.size,
401
+ :input => rack_input)
402
+
403
+ lambda {req.POST}.should.not.raise
404
+ lambda {req.POST}.should.blaming("input re-processed!").not.raise
405
+ end
406
+
407
+ specify "does conform to the Rack spec" do
408
+ app = lambda { |env|
409
+ content = Rack::Request.new(env).POST["file"].inspect
410
+ size = content.respond_to?(:bytesize) ? content.bytesize : content.size
411
+ [200, {"Content-Type" => "text/html", "Content-Length" => size.to_s}, [content]]
412
+ }
413
+
414
+ input = <<EOF
415
+ --AaB03x\r
416
+ content-disposition: form-data; name="reply"\r
417
+ \r
418
+ yes\r
419
+ --AaB03x\r
420
+ content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
421
+ Content-Type: image/jpeg\r
422
+ Content-Transfer-Encoding: base64\r
423
+ \r
424
+ /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
425
+ --AaB03x--\r
426
+ EOF
427
+ res = Rack::MockRequest.new(Rack::Lint.new(app)).get "/",
428
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
429
+ "CONTENT_LENGTH" => input.size.to_s, "rack.input" => StringIO.new(input)
430
+
431
+ res.should.be.ok
432
+ end
433
+
434
+ specify "should parse Accept-Encoding correctly" do
435
+ parser = lambda do |x|
436
+ Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => x)).accept_encoding
437
+ end
438
+
439
+ parser.call(nil).should.equal([])
440
+
441
+ parser.call("compress, gzip").should.equal([["compress", 1.0], ["gzip", 1.0]])
442
+ parser.call("").should.equal([])
443
+ parser.call("*").should.equal([["*", 1.0]])
444
+ parser.call("compress;q=0.5, gzip;q=1.0").should.equal([["compress", 0.5], ["gzip", 1.0]])
445
+ parser.call("gzip;q=1.0, identity; q=0.5, *;q=0").should.equal([["gzip", 1.0], ["identity", 0.5], ["*", 0] ])
446
+
447
+ lambda { parser.call("gzip ; q=1.0") }.should.raise(RuntimeError)
448
+ end
449
+
450
+ specify 'should provide ip information' do
451
+ app = lambda { |env|
452
+ request = Rack::Request.new(env)
453
+ response = Rack::Response.new
454
+ response.write request.ip
455
+ response.finish
456
+ }
457
+
458
+ mock = Rack::MockRequest.new(Rack::Lint.new(app))
459
+ res = mock.get '/', 'REMOTE_ADDR' => '123.123.123.123'
460
+ res.body.should.equal '123.123.123.123'
461
+
462
+ res = mock.get '/',
463
+ 'REMOTE_ADDR' => '123.123.123.123',
464
+ 'HTTP_X_FORWARDED_FOR' => '234.234.234.234'
465
+
466
+ res.body.should.equal '234.234.234.234'
467
+
468
+ res = mock.get '/',
469
+ 'REMOTE_ADDR' => '123.123.123.123',
470
+ 'HTTP_X_FORWARDED_FOR' => '234.234.234.234,212.212.212.212'
471
+
472
+ res.body.should.equal '212.212.212.212'
473
+ end
474
+
475
+ class MyRequest < Rack::Request
476
+ def params
477
+ {:foo => "bar"}
478
+ end
479
+ end
480
+
481
+ specify "should allow subclass request to be instantiated after parent request" do
482
+ env = Rack::MockRequest.env_for("/?foo=bar")
483
+
484
+ req1 = Rack::Request.new(env)
485
+ req1.GET.should.equal "foo" => "bar"
486
+ req1.params.should.equal "foo" => "bar"
487
+
488
+ req2 = MyRequest.new(env)
489
+ req2.GET.should.equal "foo" => "bar"
490
+ req2.params.should.equal :foo => "bar"
491
+ end
492
+
493
+ specify "should allow parent request to be instantiated after subclass request" do
494
+ env = Rack::MockRequest.env_for("/?foo=bar")
495
+
496
+ req1 = MyRequest.new(env)
497
+ req1.GET.should.equal "foo" => "bar"
498
+ req1.params.should.equal :foo => "bar"
499
+
500
+ req2 = Rack::Request.new(env)
501
+ req2.GET.should.equal "foo" => "bar"
502
+ req2.params.should.equal "foo" => "bar"
503
+ end
504
+ end