eac-rack 1.1.1

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