rack 1.6.13 → 2.0.9.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 (142) hide show
  1. checksums.yaml +4 -4
  2. data/COPYING +1 -1
  3. data/HISTORY.md +153 -8
  4. data/README.rdoc +35 -31
  5. data/Rakefile +6 -14
  6. data/SPEC +10 -11
  7. data/contrib/rack_logo.svg +164 -111
  8. data/example/protectedlobster.rb +1 -1
  9. data/example/protectedlobster.ru +1 -1
  10. data/lib/rack/auth/abstract/request.rb +5 -1
  11. data/lib/rack/auth/digest/params.rb +2 -3
  12. data/lib/rack/auth/digest/request.rb +1 -1
  13. data/lib/rack/body_proxy.rb +14 -9
  14. data/lib/rack/builder.rb +3 -3
  15. data/lib/rack/chunked.rb +5 -5
  16. data/lib/rack/{commonlogger.rb → common_logger.rb} +6 -3
  17. data/lib/rack/content_length.rb +2 -2
  18. data/lib/rack/deflater.rb +4 -39
  19. data/lib/rack/directory.rb +66 -54
  20. data/lib/rack/etag.rb +5 -4
  21. data/lib/rack/events.rb +154 -0
  22. data/lib/rack/file.rb +64 -40
  23. data/lib/rack/handler/cgi.rb +15 -16
  24. data/lib/rack/handler/fastcgi.rb +13 -14
  25. data/lib/rack/handler/lsws.rb +11 -11
  26. data/lib/rack/handler/scgi.rb +15 -15
  27. data/lib/rack/handler/thin.rb +3 -0
  28. data/lib/rack/handler/webrick.rb +24 -26
  29. data/lib/rack/handler.rb +3 -25
  30. data/lib/rack/head.rb +15 -17
  31. data/lib/rack/lint.rb +41 -41
  32. data/lib/rack/lobster.rb +1 -1
  33. data/lib/rack/lock.rb +15 -10
  34. data/lib/rack/logger.rb +2 -2
  35. data/lib/rack/media_type.rb +38 -0
  36. data/lib/rack/{methodoverride.rb → method_override.rb} +6 -6
  37. data/lib/rack/mime.rb +18 -5
  38. data/lib/rack/mock.rb +36 -54
  39. data/lib/rack/multipart/generator.rb +5 -5
  40. data/lib/rack/multipart/parser.rb +283 -157
  41. data/lib/rack/multipart/uploaded_file.rb +1 -2
  42. data/lib/rack/multipart.rb +36 -8
  43. data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
  44. data/lib/rack/query_parser.rb +192 -0
  45. data/lib/rack/recursive.rb +8 -8
  46. data/lib/rack/request.rb +394 -305
  47. data/lib/rack/response.rb +130 -57
  48. data/lib/rack/rewindable_input.rb +1 -12
  49. data/lib/rack/runtime.rb +10 -18
  50. data/lib/rack/sendfile.rb +5 -7
  51. data/lib/rack/server.rb +30 -23
  52. data/lib/rack/session/abstract/id.rb +110 -75
  53. data/lib/rack/session/cookie.rb +24 -17
  54. data/lib/rack/session/memcache.rb +9 -9
  55. data/lib/rack/session/pool.rb +8 -8
  56. data/lib/rack/show_exceptions.rb +386 -0
  57. data/lib/rack/{showstatus.rb → show_status.rb} +3 -3
  58. data/lib/rack/static.rb +30 -5
  59. data/lib/rack/tempfile_reaper.rb +2 -2
  60. data/lib/rack/urlmap.rb +15 -14
  61. data/lib/rack/utils.rb +156 -217
  62. data/lib/rack.rb +70 -21
  63. data/rack.gemspec +10 -9
  64. data/test/builder/an_underscore_app.rb +5 -0
  65. data/test/builder/options.ru +1 -1
  66. data/test/cgi/test.fcgi +1 -0
  67. data/test/cgi/test.gz +0 -0
  68. data/test/helper.rb +34 -0
  69. data/test/multipart/filename_with_encoded_words +7 -0
  70. data/test/multipart/filename_with_escaped_quotes_and_modification_param +1 -1
  71. data/test/multipart/filename_with_single_quote +7 -0
  72. data/test/multipart/quoted +15 -0
  73. data/test/multipart/rack-logo.png +0 -0
  74. data/test/multipart/unity3d_wwwform +11 -0
  75. data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
  76. data/test/spec_auth_basic.rb +27 -19
  77. data/test/spec_auth_digest.rb +47 -46
  78. data/test/spec_body_proxy.rb +27 -27
  79. data/test/spec_builder.rb +51 -41
  80. data/test/spec_cascade.rb +24 -22
  81. data/test/spec_cgi.rb +49 -67
  82. data/test/spec_chunked.rb +37 -35
  83. data/test/{spec_commonlogger.rb → spec_common_logger.rb} +35 -21
  84. data/test/{spec_conditionalget.rb → spec_conditional_get.rb} +29 -28
  85. data/test/spec_config.rb +3 -2
  86. data/test/spec_content_length.rb +18 -17
  87. data/test/spec_content_type.rb +13 -12
  88. data/test/spec_deflater.rb +85 -49
  89. data/test/spec_directory.rb +87 -27
  90. data/test/spec_etag.rb +32 -31
  91. data/test/spec_events.rb +133 -0
  92. data/test/spec_fastcgi.rb +50 -72
  93. data/test/spec_file.rb +120 -77
  94. data/test/spec_handler.rb +19 -34
  95. data/test/spec_head.rb +15 -14
  96. data/test/spec_lint.rb +169 -199
  97. data/test/spec_lobster.rb +24 -23
  98. data/test/spec_lock.rb +79 -39
  99. data/test/spec_logger.rb +4 -3
  100. data/test/spec_media_type.rb +42 -0
  101. data/test/{spec_methodoverride.rb → spec_method_override.rb} +34 -35
  102. data/test/spec_mime.rb +19 -19
  103. data/test/spec_mock.rb +206 -144
  104. data/test/spec_multipart.rb +329 -208
  105. data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
  106. data/test/spec_recursive.rb +17 -14
  107. data/test/spec_request.rb +796 -605
  108. data/test/spec_response.rb +233 -112
  109. data/test/spec_rewindable_input.rb +50 -40
  110. data/test/spec_runtime.rb +11 -10
  111. data/test/spec_sendfile.rb +30 -35
  112. data/test/spec_server.rb +78 -52
  113. data/test/spec_session_abstract_id.rb +11 -33
  114. data/test/spec_session_abstract_session_hash.rb +45 -0
  115. data/test/spec_session_cookie.rb +99 -67
  116. data/test/spec_session_memcache.rb +67 -68
  117. data/test/spec_session_pool.rb +52 -51
  118. data/test/{spec_showexceptions.rb → spec_show_exceptions.rb} +23 -28
  119. data/test/{spec_showstatus.rb → spec_show_status.rb} +36 -35
  120. data/test/spec_static.rb +71 -32
  121. data/test/spec_tempfile_reaper.rb +11 -10
  122. data/test/spec_thin.rb +55 -50
  123. data/test/spec_urlmap.rb +79 -78
  124. data/test/spec_utils.rb +441 -346
  125. data/test/spec_version.rb +2 -8
  126. data/test/spec_webrick.rb +93 -71
  127. data/test/static/foo.html +1 -0
  128. data/test/testrequest.rb +1 -1
  129. data/test/unregistered_handler/rack/handler/unregistered.rb +1 -1
  130. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +1 -1
  131. metadata +95 -74
  132. data/KNOWN-ISSUES +0 -44
  133. data/lib/rack/backports/uri/common_18.rb +0 -56
  134. data/lib/rack/backports/uri/common_192.rb +0 -52
  135. data/lib/rack/backports/uri/common_193.rb +0 -29
  136. data/lib/rack/handler/evented_mongrel.rb +0 -8
  137. data/lib/rack/handler/mongrel.rb +0 -106
  138. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  139. data/lib/rack/showexceptions.rb +0 -387
  140. data/lib/rack/utils/okjson.rb +0 -600
  141. data/test/spec_mongrel.rb +0 -182
  142. /data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
data/test/spec_request.rb CHANGED
@@ -1,574 +1,724 @@
1
+ require 'minitest/autorun'
1
2
  require 'stringio'
2
3
  require 'cgi'
3
4
  require 'rack/request'
4
5
  require 'rack/mock'
6
+ require 'rack/multipart'
5
7
  require 'securerandom'
6
8
 
7
- describe Rack::Request do
8
- should "wrap the rack variables" do
9
- req = Rack::Request.new(Rack::MockRequest.env_for("http://example.com:8080/"))
9
+ class RackRequestTest < Minitest::Spec
10
+ it "copies the env when duping" do
11
+ req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
12
+ refute_same req.env, req.dup.env
13
+ end
14
+
15
+ it 'can check if something has been set' do
16
+ req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
17
+ refute req.has_header?("FOO")
18
+ end
19
+
20
+ it "can get a key from the env" do
21
+ req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
22
+ assert_equal "example.com", req.get_header("SERVER_NAME")
23
+ end
24
+
25
+ it 'can calculate the authority' do
26
+ req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
27
+ assert_equal "example.com:8080", req.authority
28
+ end
29
+
30
+ it 'can calculate the authority without a port' do
31
+ req = make_request(Rack::MockRequest.env_for("http://example.com/"))
32
+ assert_equal "example.com:80", req.authority
33
+ end
10
34
 
11
- req.body.should.respond_to? :gets
12
- req.scheme.should.equal "http"
13
- req.request_method.should.equal "GET"
35
+ it 'can calculate the authority without a port on ssl' do
36
+ req = make_request(Rack::MockRequest.env_for("https://example.com/"))
37
+ assert_equal "example.com:443", req.authority
38
+ end
14
39
 
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
- req.should.not.be.patch
40
+ it 'yields to the block if no value has been set' do
41
+ req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
42
+ yielded = false
43
+ req.fetch_header("FOO") do
44
+ yielded = true
45
+ req.set_header "FOO", 'bar'
46
+ end
21
47
 
22
- req.script_name.should.equal ""
23
- req.path_info.should.equal "/"
24
- req.query_string.should.equal ""
48
+ assert yielded
49
+ assert_equal "bar", req.get_header("FOO")
50
+ end
25
51
 
26
- req.host.should.equal "example.com"
27
- req.port.should.equal 8080
52
+ it 'can iterate over values' do
53
+ req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
54
+ req.set_header 'foo', 'bar'
55
+ hash = {}
56
+ req.each_header do |k,v|
57
+ hash[k] = v
58
+ end
59
+ assert_equal 'bar', hash['foo']
60
+ end
28
61
 
29
- req.content_length.should.equal "0"
30
- req.content_type.should.be.nil
62
+ it 'can set values in the env' do
63
+ req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
64
+ req.set_header("FOO", "BAR")
65
+ assert_equal "BAR", req.get_header("FOO")
31
66
  end
32
67
 
33
- should "figure out the correct host" do
34
- req = Rack::Request.new \
68
+ it 'can add to multivalued headers in the env' do
69
+ req = make_request(Rack::MockRequest.env_for('http://example.com:8080/'))
70
+
71
+ assert_equal '1', req.add_header('FOO', '1')
72
+ assert_equal '1', req.get_header('FOO')
73
+
74
+ assert_equal '1,2', req.add_header('FOO', '2')
75
+ assert_equal '1,2', req.get_header('FOO')
76
+
77
+ assert_equal '1,2', req.add_header('FOO', nil)
78
+ assert_equal '1,2', req.get_header('FOO')
79
+ end
80
+
81
+ it 'can delete env values' do
82
+ req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
83
+ req.set_header 'foo', 'bar'
84
+ assert req.has_header? 'foo'
85
+ req.delete_header 'foo'
86
+ refute req.has_header? 'foo'
87
+ end
88
+
89
+ it "wrap the rack variables" do
90
+ req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
91
+
92
+ req.body.must_respond_to :gets
93
+ req.scheme.must_equal "http"
94
+ req.request_method.must_equal "GET"
95
+
96
+ req.must_be :get?
97
+ req.wont_be :post?
98
+ req.wont_be :put?
99
+ req.wont_be :delete?
100
+ req.wont_be :head?
101
+ req.wont_be :patch?
102
+
103
+ req.script_name.must_equal ""
104
+ req.path_info.must_equal "/"
105
+ req.query_string.must_equal ""
106
+
107
+ req.host.must_equal "example.com"
108
+ req.port.must_equal 8080
109
+
110
+ req.content_length.must_equal "0"
111
+ req.content_type.must_be_nil
112
+ end
113
+
114
+ it "figure out the correct host" do
115
+ req = make_request \
35
116
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
36
- req.host.should.equal "www2.example.org"
117
+ req.host.must_equal "www2.example.org"
37
118
 
38
- req = Rack::Request.new \
119
+ req = make_request \
39
120
  Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
40
- req.host.should.equal "example.org"
121
+ req.host.must_equal "example.org"
41
122
 
42
- req = Rack::Request.new \
123
+ req = make_request \
43
124
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
44
- req.host.should.equal "example.org"
125
+ req.host.must_equal "example.org"
45
126
 
46
127
  env = Rack::MockRequest.env_for("/", "SERVER_ADDR" => "192.168.1.1", "SERVER_PORT" => "9292")
47
128
  env.delete("SERVER_NAME")
48
- req = Rack::Request.new(env)
49
- req.host.should.equal "192.168.1.1"
129
+ req = make_request(env)
130
+ req.host.must_equal "192.168.1.1"
50
131
 
51
132
  env = Rack::MockRequest.env_for("/")
52
133
  env.delete("SERVER_NAME")
53
- req = Rack::Request.new(env)
54
- req.host.should.equal ""
134
+ req = make_request(env)
135
+ req.host.must_equal ""
55
136
  end
56
137
 
57
- should "figure out the correct port" do
58
- req = Rack::Request.new \
138
+ it "figure out the correct port" do
139
+ req = make_request \
59
140
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
60
- req.port.should.equal 80
141
+ req.port.must_equal 80
61
142
 
62
- req = Rack::Request.new \
143
+ req = make_request \
63
144
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org:81")
64
- req.port.should.equal 81
145
+ req.port.must_equal 81
65
146
 
66
- req = Rack::Request.new \
147
+ req = make_request \
67
148
  Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
68
- req.port.should.equal 9292
149
+ req.port.must_equal 9292
69
150
 
70
- req = Rack::Request.new \
151
+ req = make_request \
71
152
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
72
- req.port.should.equal 9292
153
+ req.port.must_equal 9292
73
154
 
74
- req = Rack::Request.new \
155
+ req = make_request \
75
156
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org")
76
- req.port.should.equal 80
157
+ req.port.must_equal 80
77
158
 
78
- req = Rack::Request.new \
159
+ req = make_request \
79
160
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_SSL" => "on")
80
- req.port.should.equal 443
161
+ req.port.must_equal 443
81
162
 
82
- req = Rack::Request.new \
163
+ req = make_request \
83
164
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_PROTO" => "https")
84
- req.port.should.equal 443
165
+ req.port.must_equal 443
85
166
 
86
- req = Rack::Request.new \
167
+ req = make_request \
87
168
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_PORT" => "9393")
88
- req.port.should.equal 9393
169
+ req.port.must_equal 9393
89
170
 
90
- req = Rack::Request.new \
171
+ req = make_request \
91
172
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9393", "SERVER_PORT" => "80")
92
- req.port.should.equal 9393
173
+ req.port.must_equal 9393
93
174
 
94
- req = Rack::Request.new \
175
+ req = make_request \
95
176
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "SERVER_PORT" => "9393")
96
- req.port.should.equal 80
177
+ req.port.must_equal 80
97
178
 
98
- req = Rack::Request.new \
179
+ req = make_request \
99
180
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost", "HTTP_X_FORWARDED_PROTO" => "https", "SERVER_PORT" => "80")
100
- req.port.should.equal 443
181
+ req.port.must_equal 443
101
182
 
102
- req = Rack::Request.new \
183
+ req = make_request \
103
184
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost", "HTTP_X_FORWARDED_PROTO" => "https,https", "SERVER_PORT" => "80")
104
- req.port.should.equal 443
185
+ req.port.must_equal 443
105
186
  end
106
187
 
107
- should "figure out the correct host with port" do
108
- req = Rack::Request.new \
188
+ it "figure out the correct host with port" do
189
+ req = make_request \
109
190
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
110
- req.host_with_port.should.equal "www2.example.org"
191
+ req.host_with_port.must_equal "www2.example.org"
111
192
 
112
- req = Rack::Request.new \
193
+ req = make_request \
113
194
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81")
114
- req.host_with_port.should.equal "localhost:81"
195
+ req.host_with_port.must_equal "localhost:81"
115
196
 
116
- req = Rack::Request.new \
197
+ req = make_request \
117
198
  Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
118
- req.host_with_port.should.equal "example.org:9292"
199
+ req.host_with_port.must_equal "example.org:9292"
119
200
 
120
- req = Rack::Request.new \
201
+ req = make_request \
121
202
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
122
- req.host_with_port.should.equal "example.org:9292"
203
+ req.host_with_port.must_equal "example.org:9292"
123
204
 
124
- req = Rack::Request.new \
205
+ req = make_request \
125
206
  Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "SERVER_PORT" => "9393")
126
- req.host_with_port.should.equal "example.org"
207
+ req.host_with_port.must_equal "example.org"
127
208
  end
128
209
 
129
- should "parse the query string" do
130
- req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
131
- req.query_string.should.equal "foo=bar&quux=bla"
132
- req.GET.should.equal "foo" => "bar", "quux" => "bla"
133
- req.POST.should.be.empty
134
- req.params.should.equal "foo" => "bar", "quux" => "bla"
210
+ it "parse the query string" do
211
+ req = make_request(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
212
+ req.query_string.must_equal "foo=bar&quux=bla"
213
+ req.GET.must_equal "foo" => "bar", "quux" => "bla"
214
+ req.POST.must_be :empty?
215
+ req.params.must_equal "foo" => "bar", "quux" => "bla"
135
216
  end
136
217
 
137
- should "not truncate query strings containing semi-colons #543 only in POST" do
218
+ it "not truncate query strings containing semi-colons #543 only in POST" do
138
219
  mr = Rack::MockRequest.env_for("/",
139
220
  "REQUEST_METHOD" => 'POST',
140
221
  :input => "foo=bar&quux=b;la")
141
- req = Rack::Request.new mr
142
- req.query_string.should.equal ""
143
- req.GET.should.be.empty
144
- req.POST.should.equal "foo" => "bar", "quux" => "b;la"
145
- req.params.should.equal req.GET.merge(req.POST)
222
+ req = make_request mr
223
+ req.query_string.must_equal ""
224
+ req.GET.must_be :empty?
225
+ req.POST.must_equal "foo" => "bar", "quux" => "b;la"
226
+ req.params.must_equal req.GET.merge(req.POST)
227
+ end
228
+
229
+ it "should use the query_parser for query parsing" do
230
+ c = Class.new(Rack::QueryParser::Params) do
231
+ def initialize(*)
232
+ super
233
+ @params = Hash.new{|h,k| h[k.to_s] if k.is_a?(Symbol)}
234
+ end
235
+ end
236
+ parser = Rack::QueryParser.new(c, 65536, 100)
237
+ c = Class.new(Rack::Request) do
238
+ define_method(:query_parser) do
239
+ parser
240
+ end
241
+ end
242
+ req = c.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
243
+ req.GET[:foo].must_equal "bar"
244
+ req.GET[:quux].must_equal "bla"
245
+ req.params[:foo].must_equal "bar"
246
+ req.params[:quux].must_equal "bla"
146
247
  end
147
248
 
148
- should "use semi-colons as separators for query strings in GET" do
149
- req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=b;la;wun=duh"))
150
- req.query_string.should.equal "foo=bar&quux=b;la;wun=duh"
151
- req.GET.should.equal "foo" => "bar", "quux" => "b", "la" => nil, "wun" => "duh"
152
- req.POST.should.be.empty
153
- req.params.should.equal "foo" => "bar", "quux" => "b", "la" => nil, "wun" => "duh"
249
+ it "use semi-colons as separators for query strings in GET" do
250
+ req = make_request(Rack::MockRequest.env_for("/?foo=bar&quux=b;la;wun=duh"))
251
+ req.query_string.must_equal "foo=bar&quux=b;la;wun=duh"
252
+ req.GET.must_equal "foo" => "bar", "quux" => "b", "la" => nil, "wun" => "duh"
253
+ req.POST.must_be :empty?
254
+ req.params.must_equal "foo" => "bar", "quux" => "b", "la" => nil, "wun" => "duh"
154
255
  end
155
256
 
156
- should "limit the keys from the GET query string" do
257
+ it "limit the keys from the GET query string" do
157
258
  env = Rack::MockRequest.env_for("/?foo=bar")
158
259
 
159
260
  old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1
160
261
  begin
161
- req = Rack::Request.new(env)
162
- lambda { req.GET }.should.raise(RangeError)
262
+ req = make_request(env)
263
+ lambda { req.GET }.must_raise RangeError
163
264
  ensure
164
265
  Rack::Utils.key_space_limit = old
165
266
  end
166
267
  end
167
268
 
168
- should "limit the key size per nested params hash" do
269
+ it "limit the key size per nested params hash" do
169
270
  nested_query = Rack::MockRequest.env_for("/?foo%5Bbar%5D%5Bbaz%5D%5Bqux%5D=1")
170
271
  plain_query = Rack::MockRequest.env_for("/?foo_bar__baz__qux_=1")
171
272
 
172
273
  old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 3
173
274
  begin
174
- lambda { Rack::Request.new(nested_query).GET }.should.not.raise(RangeError)
175
- lambda { Rack::Request.new(plain_query).GET }.should.raise(RangeError)
275
+ exp = {"foo"=>{"bar"=>{"baz"=>{"qux"=>"1"}}}}
276
+ make_request(nested_query).GET.must_equal exp
277
+ lambda { make_request(plain_query).GET }.must_raise RangeError
176
278
  ensure
177
279
  Rack::Utils.key_space_limit = old
178
280
  end
179
281
  end
180
282
 
181
- should "not unify GET and POST when calling params" do
283
+ it "not unify GET and POST when calling params" do
182
284
  mr = Rack::MockRequest.env_for("/?foo=quux",
183
285
  "REQUEST_METHOD" => 'POST',
184
286
  :input => "foo=bar&quux=bla"
185
287
  )
186
- req = Rack::Request.new mr
288
+ req = make_request mr
187
289
 
188
290
  req.params
189
291
 
190
- req.GET.should.equal "foo" => "quux"
191
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
192
- req.params.should.equal req.GET.merge(req.POST)
292
+ req.GET.must_equal "foo" => "quux"
293
+ req.POST.must_equal "foo" => "bar", "quux" => "bla"
294
+ req.params.must_equal req.GET.merge(req.POST)
193
295
  end
194
296
 
195
- should "raise if input params has invalid %-encoding" do
297
+ it "use the query_parser's params_class for multipart params" do
298
+ c = Class.new(Rack::QueryParser::Params) do
299
+ def initialize(*)
300
+ super
301
+ @params = Hash.new{|h,k| h[k.to_s] if k.is_a?(Symbol)}
302
+ end
303
+ end
304
+ parser = Rack::QueryParser.new(c, 65536, 100)
305
+ c = Class.new(Rack::Request) do
306
+ define_method(:query_parser) do
307
+ parser
308
+ end
309
+ end
310
+ mr = Rack::MockRequest.env_for("/?foo=quux",
311
+ "REQUEST_METHOD" => 'POST',
312
+ :input => "foo=bar&quux=bla"
313
+ )
314
+ req = c.new mr
315
+
316
+ req.params
317
+
318
+ req.GET[:foo].must_equal "quux"
319
+ req.POST[:foo].must_equal "bar"
320
+ req.POST[:quux].must_equal "bla"
321
+ req.params[:foo].must_equal "bar"
322
+ req.params[:quux].must_equal "bla"
323
+ end
324
+
325
+ it "raise if input params has invalid %-encoding" do
196
326
  mr = Rack::MockRequest.env_for("/?foo=quux",
197
327
  "REQUEST_METHOD" => 'POST',
198
328
  :input => "a%=1"
199
329
  )
200
- req = Rack::Request.new mr
330
+ req = make_request mr
201
331
 
202
- lambda { req.POST }.
203
- should.raise(Rack::Utils::InvalidParameterError).
204
- message.should.equal "invalid %-encoding (a%)"
332
+ lambda { req.POST }.must_raise(Rack::Utils::InvalidParameterError).
333
+ message.must_equal "invalid %-encoding (a%)"
205
334
  end
206
335
 
207
- should "raise if rack.input is missing" do
208
- req = Rack::Request.new({})
209
- lambda { req.POST }.should.raise(RuntimeError)
336
+ it "raise if rack.input is missing" do
337
+ req = make_request({})
338
+ lambda { req.POST }.must_raise RuntimeError
210
339
  end
211
340
 
212
- should "parse POST data when method is POST and no Content-Type given" do
213
- req = Rack::Request.new \
341
+ it "parse POST data when method is POST and no Content-Type given" do
342
+ req = make_request \
214
343
  Rack::MockRequest.env_for("/?foo=quux",
215
344
  "REQUEST_METHOD" => 'POST',
216
345
  :input => "foo=bar&quux=bla")
217
- req.content_type.should.be.nil
218
- req.media_type.should.be.nil
219
- req.query_string.should.equal "foo=quux"
220
- req.GET.should.equal "foo" => "quux"
221
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
222
- req.params.should.equal "foo" => "bar", "quux" => "bla"
346
+ req.content_type.must_be_nil
347
+ req.media_type.must_be_nil
348
+ req.query_string.must_equal "foo=quux"
349
+ req.GET.must_equal "foo" => "quux"
350
+ req.POST.must_equal "foo" => "bar", "quux" => "bla"
351
+ req.params.must_equal "foo" => "bar", "quux" => "bla"
223
352
  end
224
353
 
225
- should "limit the keys from the POST form data" do
354
+ it "limit the keys from the POST form data" do
226
355
  env = Rack::MockRequest.env_for("",
227
356
  "REQUEST_METHOD" => 'POST',
228
357
  :input => "foo=bar&quux=bla")
229
358
 
230
359
  old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1
231
360
  begin
232
- req = Rack::Request.new(env)
233
- lambda { req.POST }.should.raise(RangeError)
361
+ req = make_request(env)
362
+ lambda { req.POST }.must_raise RangeError
234
363
  ensure
235
364
  Rack::Utils.key_space_limit = old
236
365
  end
237
366
  end
238
367
 
239
- should "parse POST data with explicit content type regardless of method" do
240
- req = Rack::Request.new \
368
+ it "parse POST data with explicit content type regardless of method" do
369
+ req = make_request \
241
370
  Rack::MockRequest.env_for("/",
242
371
  "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
243
372
  :input => "foo=bar&quux=bla")
244
- req.content_type.should.equal 'application/x-www-form-urlencoded;foo=bar'
245
- req.media_type.should.equal 'application/x-www-form-urlencoded'
246
- req.media_type_params['foo'].should.equal 'bar'
247
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
248
- req.params.should.equal "foo" => "bar", "quux" => "bla"
373
+ req.content_type.must_equal 'application/x-www-form-urlencoded;foo=bar'
374
+ req.media_type.must_equal 'application/x-www-form-urlencoded'
375
+ req.media_type_params['foo'].must_equal 'bar'
376
+ req.POST.must_equal "foo" => "bar", "quux" => "bla"
377
+ req.params.must_equal "foo" => "bar", "quux" => "bla"
249
378
  end
250
379
 
251
- should "not parse POST data when media type is not form-data" do
252
- req = Rack::Request.new \
380
+ it "not parse POST data when media type is not form-data" do
381
+ req = make_request \
253
382
  Rack::MockRequest.env_for("/?foo=quux",
254
383
  "REQUEST_METHOD" => 'POST',
255
384
  "CONTENT_TYPE" => 'text/plain;charset=utf-8',
256
385
  :input => "foo=bar&quux=bla")
257
- req.content_type.should.equal 'text/plain;charset=utf-8'
258
- req.media_type.should.equal 'text/plain'
259
- req.media_type_params['charset'].should.equal 'utf-8'
260
- req.POST.should.be.empty
261
- req.params.should.equal "foo" => "quux"
262
- req.body.read.should.equal "foo=bar&quux=bla"
386
+ req.content_type.must_equal 'text/plain;charset=utf-8'
387
+ req.media_type.must_equal 'text/plain'
388
+ req.media_type_params['charset'].must_equal 'utf-8'
389
+ req.POST.must_be :empty?
390
+ req.params.must_equal "foo" => "quux"
391
+ req.body.read.must_equal "foo=bar&quux=bla"
263
392
  end
264
393
 
265
- should "parse POST data on PUT when media type is form-data" do
266
- req = Rack::Request.new \
394
+ it "parse POST data on PUT when media type is form-data" do
395
+ req = make_request \
267
396
  Rack::MockRequest.env_for("/?foo=quux",
268
397
  "REQUEST_METHOD" => 'PUT',
269
398
  "CONTENT_TYPE" => 'application/x-www-form-urlencoded',
270
399
  :input => "foo=bar&quux=bla")
271
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
272
- req.body.read.should.equal "foo=bar&quux=bla"
400
+ req.POST.must_equal "foo" => "bar", "quux" => "bla"
401
+ req.body.read.must_equal "foo=bar&quux=bla"
273
402
  end
274
403
 
275
- should "rewind input after parsing POST data" do
404
+ it "rewind input after parsing POST data" do
276
405
  input = StringIO.new("foo=bar&quux=bla")
277
- req = Rack::Request.new \
406
+ req = make_request \
278
407
  Rack::MockRequest.env_for("/",
279
408
  "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
280
409
  :input => input)
281
- req.params.should.equal "foo" => "bar", "quux" => "bla"
282
- input.read.should.equal "foo=bar&quux=bla"
410
+ req.params.must_equal "foo" => "bar", "quux" => "bla"
411
+ input.read.must_equal "foo=bar&quux=bla"
412
+ end
413
+
414
+ it "safely accepts POST requests with empty body" do
415
+ mr = Rack::MockRequest.env_for("/",
416
+ "REQUEST_METHOD" => "POST",
417
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
418
+ "CONTENT_LENGTH" => '0',
419
+ :input => nil)
420
+
421
+ req = make_request mr
422
+ req.query_string.must_equal ""
423
+ req.GET.must_be :empty?
424
+ req.POST.must_be :empty?
425
+ req.params.must_equal({})
283
426
  end
284
427
 
285
- should "clean up Safari's ajax POST body" do
286
- req = Rack::Request.new \
428
+ it "clean up Safari's ajax POST body" do
429
+ req = make_request \
287
430
  Rack::MockRequest.env_for("/",
288
431
  'REQUEST_METHOD' => 'POST', :input => "foo=bar&quux=bla\0")
289
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
432
+ req.POST.must_equal "foo" => "bar", "quux" => "bla"
290
433
  end
291
434
 
292
- should "get value by key from params with #[]" do
293
- req = Rack::Request.new \
435
+ it "get value by key from params with #[]" do
436
+ req = make_request \
294
437
  Rack::MockRequest.env_for("?foo=quux")
295
- req['foo'].should.equal 'quux'
296
- req[:foo].should.equal 'quux'
438
+ req['foo'].must_equal 'quux'
439
+ req[:foo].must_equal 'quux'
297
440
  end
298
441
 
299
- should "set value to key on params with #[]=" do
300
- req = Rack::Request.new \
442
+ it "set value to key on params with #[]=" do
443
+ req = make_request \
301
444
  Rack::MockRequest.env_for("?foo=duh")
302
- req['foo'].should.equal 'duh'
303
- req[:foo].should.equal 'duh'
304
- req.params.should.equal 'foo' => 'duh'
445
+ req['foo'].must_equal 'duh'
446
+ req[:foo].must_equal 'duh'
447
+ req.params.must_equal 'foo' => 'duh'
448
+
449
+ if req.delegate?
450
+ skip "delegate requests don't cache params, so mutations have no impact"
451
+ end
305
452
 
306
453
  req['foo'] = 'bar'
307
- req.params.should.equal 'foo' => 'bar'
308
- req['foo'].should.equal 'bar'
309
- req[:foo].should.equal 'bar'
454
+ req.params.must_equal 'foo' => 'bar'
455
+ req['foo'].must_equal 'bar'
456
+ req[:foo].must_equal 'bar'
310
457
 
311
458
  req[:foo] = 'jaz'
312
- req.params.should.equal 'foo' => 'jaz'
313
- req['foo'].should.equal 'jaz'
314
- req[:foo].should.equal 'jaz'
459
+ req.params.must_equal 'foo' => 'jaz'
460
+ req['foo'].must_equal 'jaz'
461
+ req[:foo].must_equal 'jaz'
315
462
  end
316
463
 
317
- should "return values for the keys in the order given from values_at" do
318
- req = Rack::Request.new \
464
+ it "return values for the keys in the order given from values_at" do
465
+ req = make_request \
319
466
  Rack::MockRequest.env_for("?foo=baz&wun=der&bar=ful")
320
- req.values_at('foo').should.equal ['baz']
321
- req.values_at('foo', 'wun').should.equal ['baz', 'der']
322
- req.values_at('bar', 'foo', 'wun').should.equal ['ful', 'baz', 'der']
467
+ req.values_at('foo').must_equal ['baz']
468
+ req.values_at('foo', 'wun').must_equal ['baz', 'der']
469
+ req.values_at('bar', 'foo', 'wun').must_equal ['ful', 'baz', 'der']
323
470
  end
324
471
 
325
- should "extract referrer correctly" do
326
- req = Rack::Request.new \
472
+ it "extract referrer correctly" do
473
+ req = make_request \
327
474
  Rack::MockRequest.env_for("/", "HTTP_REFERER" => "/some/path")
328
- req.referer.should.equal "/some/path"
475
+ req.referer.must_equal "/some/path"
329
476
 
330
- req = Rack::Request.new \
477
+ req = make_request \
331
478
  Rack::MockRequest.env_for("/")
332
- req.referer.should.equal nil
479
+ req.referer.must_be_nil
333
480
  end
334
481
 
335
- should "extract user agent correctly" do
336
- req = Rack::Request.new \
482
+ it "extract user agent correctly" do
483
+ req = make_request \
337
484
  Rack::MockRequest.env_for("/", "HTTP_USER_AGENT" => "Mozilla/4.0 (compatible)")
338
- req.user_agent.should.equal "Mozilla/4.0 (compatible)"
485
+ req.user_agent.must_equal "Mozilla/4.0 (compatible)"
339
486
 
340
- req = Rack::Request.new \
487
+ req = make_request \
341
488
  Rack::MockRequest.env_for("/")
342
- req.user_agent.should.equal nil
489
+ req.user_agent.must_be_nil
343
490
  end
344
491
 
345
- should "treat missing content type as nil" do
346
- req = Rack::Request.new \
492
+ it "treat missing content type as nil" do
493
+ req = make_request \
347
494
  Rack::MockRequest.env_for("/")
348
- req.content_type.should.equal nil
495
+ req.content_type.must_be_nil
349
496
  end
350
497
 
351
- should "treat empty content type as nil" do
352
- req = Rack::Request.new \
498
+ it "treat empty content type as nil" do
499
+ req = make_request \
353
500
  Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "")
354
- req.content_type.should.equal nil
501
+ req.content_type.must_be_nil
355
502
  end
356
503
 
357
- should "return nil media type for empty content type" do
358
- req = Rack::Request.new \
504
+ it "return nil media type for empty content type" do
505
+ req = make_request \
359
506
  Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "")
360
- req.media_type.should.equal nil
507
+ req.media_type.must_be_nil
361
508
  end
362
509
 
363
- should "cache, but invalidates the cache" do
364
- req = Rack::Request.new \
510
+ it "cache, but invalidates the cache" do
511
+ req = make_request \
365
512
  Rack::MockRequest.env_for("/?foo=quux",
366
513
  "CONTENT_TYPE" => "application/x-www-form-urlencoded",
367
514
  :input => "foo=bar&quux=bla")
368
- req.GET.should.equal "foo" => "quux"
369
- req.GET.should.equal "foo" => "quux"
370
- req.env["QUERY_STRING"] = "bla=foo"
371
- req.GET.should.equal "bla" => "foo"
372
- req.GET.should.equal "bla" => "foo"
515
+ req.GET.must_equal "foo" => "quux"
516
+ req.GET.must_equal "foo" => "quux"
517
+ req.set_header("QUERY_STRING", "bla=foo")
518
+ req.GET.must_equal "bla" => "foo"
519
+ req.GET.must_equal "bla" => "foo"
373
520
 
374
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
375
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
376
- req.env["rack.input"] = StringIO.new("foo=bla&quux=bar")
377
- req.POST.should.equal "foo" => "bla", "quux" => "bar"
378
- req.POST.should.equal "foo" => "bla", "quux" => "bar"
521
+ req.POST.must_equal "foo" => "bar", "quux" => "bla"
522
+ req.POST.must_equal "foo" => "bar", "quux" => "bla"
523
+ req.set_header("rack.input", StringIO.new("foo=bla&quux=bar"))
524
+ req.POST.must_equal "foo" => "bla", "quux" => "bar"
525
+ req.POST.must_equal "foo" => "bla", "quux" => "bar"
379
526
  end
380
527
 
381
- should "figure out if called via XHR" do
382
- req = Rack::Request.new(Rack::MockRequest.env_for(""))
383
- req.should.not.be.xhr
528
+ it "figure out if called via XHR" do
529
+ req = make_request(Rack::MockRequest.env_for(""))
530
+ req.wont_be :xhr?
384
531
 
385
- req = Rack::Request.new \
532
+ req = make_request \
386
533
  Rack::MockRequest.env_for("", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest")
387
- req.should.be.xhr
534
+ req.must_be :xhr?
388
535
  end
389
536
 
390
- should "ssl detection" do
391
- request = Rack::Request.new(Rack::MockRequest.env_for("/"))
392
- request.scheme.should.equal "http"
393
- request.should.not.be.ssl?
537
+ it "ssl detection" do
538
+ request = make_request(Rack::MockRequest.env_for("/"))
539
+ request.scheme.must_equal "http"
540
+ request.wont_be :ssl?
394
541
 
395
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTPS' => 'on'))
396
- request.scheme.should.equal "https"
397
- request.should.be.ssl?
542
+ request = make_request(Rack::MockRequest.env_for("/", 'HTTPS' => 'on'))
543
+ request.scheme.must_equal "https"
544
+ request.must_be :ssl?
398
545
 
399
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'rack.url_scheme' => 'https'))
400
- request.scheme.should.equal "https"
401
- request.should.be.ssl?
546
+ request = make_request(Rack::MockRequest.env_for("/", 'rack.url_scheme' => 'https'))
547
+ request.scheme.must_equal "https"
548
+ request.must_be :ssl?
402
549
 
403
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8080'))
404
- request.scheme.should.equal "http"
405
- request.should.not.be.ssl?
550
+ request = make_request(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8080'))
551
+ request.scheme.must_equal "http"
552
+ request.wont_be :ssl?
406
553
 
407
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTPS' => 'on'))
408
- request.scheme.should.equal "https"
409
- request.should.be.ssl?
554
+ request = make_request(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTPS' => 'on'))
555
+ request.scheme.must_equal "https"
556
+ request.must_be :ssl?
410
557
 
411
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTP_X_FORWARDED_SSL' => 'on'))
412
- request.scheme.should.equal "https"
413
- request.should.be.ssl?
558
+ request = make_request(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTP_X_FORWARDED_SSL' => 'on'))
559
+ request.scheme.must_equal "https"
560
+ request.must_be :ssl?
414
561
 
415
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_SCHEME' => 'https'))
416
- request.scheme.should.equal "https"
417
- request.should.be.ssl?
562
+ request = make_request(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_SCHEME' => 'https'))
563
+ request.scheme.must_equal "https"
564
+ request.must_be :ssl?
418
565
 
419
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https'))
420
- request.scheme.should.equal "https"
421
- request.should.be.ssl?
566
+ request = make_request(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https'))
567
+ request.scheme.must_equal "https"
568
+ request.must_be :ssl?
422
569
 
423
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https, http, http'))
424
- request.scheme.should.equal "https"
425
- request.should.be.ssl?
570
+ request = make_request(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https, http, http'))
571
+ request.scheme.must_equal "https"
572
+ request.must_be :ssl?
426
573
  end
427
574
 
428
- should "prevent scheme abuse" do
429
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_SCHEME' => 'a."><script>alert(1)</script>'))
430
- request.scheme.should.not.equal 'a."><script>alert(1)</script>'
575
+ it "prevents scheme abuse" do
576
+ request = make_request(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_SCHEME' => 'a."><script>alert(1)</script>'))
577
+ request.scheme.must_equal 'http'
431
578
  end
432
579
 
433
- should "parse cookies" do
434
- req = Rack::Request.new \
580
+ it "parse cookies" do
581
+ req = make_request \
435
582
  Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
436
- req.cookies.should.equal "foo" => "bar", "quux" => "h&m"
437
- req.cookies.should.equal "foo" => "bar", "quux" => "h&m"
438
- req.env.delete("HTTP_COOKIE")
439
- req.cookies.should.equal({})
583
+ req.cookies.must_equal "foo" => "bar", "quux" => "h&m"
584
+ req.cookies.must_equal "foo" => "bar", "quux" => "h&m"
585
+ req.delete_header("HTTP_COOKIE")
586
+ req.cookies.must_equal({})
440
587
  end
441
588
 
442
- should "always return the same hash object" do
443
- req = Rack::Request.new \
589
+ it "always return the same hash object" do
590
+ req = make_request \
444
591
  Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
445
592
  hash = req.cookies
446
593
  req.env.delete("HTTP_COOKIE")
447
- req.cookies.should.equal(hash)
594
+ req.cookies.must_equal hash
448
595
  req.env["HTTP_COOKIE"] = "zoo=m"
449
- req.cookies.should.equal(hash)
596
+ req.cookies.must_equal hash
450
597
  end
451
598
 
452
- should "modify the cookies hash in place" do
453
- req = Rack::Request.new(Rack::MockRequest.env_for(""))
454
- req.cookies.should.equal({})
599
+ it "modify the cookies hash in place" do
600
+ req = make_request(Rack::MockRequest.env_for(""))
601
+ req.cookies.must_equal({})
455
602
  req.cookies['foo'] = 'bar'
456
- req.cookies.should.equal 'foo' => 'bar'
603
+ req.cookies.must_equal 'foo' => 'bar'
457
604
  end
458
605
 
459
- should "not modify the params hash in place" do
606
+ it "not modify the params hash in place" do
460
607
  e = Rack::MockRequest.env_for("")
461
- req1 = Rack::Request.new(e)
462
- req1.params.should.equal({})
608
+ req1 = make_request(e)
609
+ if req1.delegate?
610
+ skip "delegate requests don't cache params, so mutations have no impact"
611
+ end
612
+ req1.params.must_equal({})
463
613
  req1.params['foo'] = 'bar'
464
- req1.params.should.equal 'foo' => 'bar'
465
- req2 = Rack::Request.new(e)
466
- req2.params.should.equal({})
614
+ req1.params.must_equal 'foo' => 'bar'
615
+ req2 = make_request(e)
616
+ req2.params.must_equal({})
467
617
  end
468
618
 
469
- should "modify params hash if param is in GET" do
619
+ it "modify params hash if param is in GET" do
470
620
  e = Rack::MockRequest.env_for("?foo=duh")
471
- req1 = Rack::Request.new(e)
472
- req1.params.should.equal 'foo' => 'duh'
621
+ req1 = make_request(e)
622
+ req1.params.must_equal 'foo' => 'duh'
473
623
  req1.update_param 'foo', 'bar'
474
- req1.params.should.equal 'foo' => 'bar'
475
- req2 = Rack::Request.new(e)
476
- req2.params.should.equal 'foo' => 'bar'
624
+ req1.params.must_equal 'foo' => 'bar'
625
+ req2 = make_request(e)
626
+ req2.params.must_equal 'foo' => 'bar'
477
627
  end
478
628
 
479
- should "modify params hash if param is in POST" do
629
+ it "modify params hash if param is in POST" do
480
630
  e = Rack::MockRequest.env_for("", "REQUEST_METHOD" => 'POST', :input => 'foo=duh')
481
- req1 = Rack::Request.new(e)
482
- req1.params.should.equal 'foo' => 'duh'
631
+ req1 = make_request(e)
632
+ req1.params.must_equal 'foo' => 'duh'
483
633
  req1.update_param 'foo', 'bar'
484
- req1.params.should.equal 'foo' => 'bar'
485
- req2 = Rack::Request.new(e)
486
- req2.params.should.equal 'foo' => 'bar'
634
+ req1.params.must_equal 'foo' => 'bar'
635
+ req2 = make_request(e)
636
+ req2.params.must_equal 'foo' => 'bar'
487
637
  end
488
638
 
489
- should "modify params hash, even if param didn't exist before" do
639
+ it "modify params hash, even if param didn't exist before" do
490
640
  e = Rack::MockRequest.env_for("")
491
- req1 = Rack::Request.new(e)
492
- req1.params.should.equal({})
641
+ req1 = make_request(e)
642
+ req1.params.must_equal({})
493
643
  req1.update_param 'foo', 'bar'
494
- req1.params.should.equal 'foo' => 'bar'
495
- req2 = Rack::Request.new(e)
496
- req2.params.should.equal 'foo' => 'bar'
644
+ req1.params.must_equal 'foo' => 'bar'
645
+ req2 = make_request(e)
646
+ req2.params.must_equal 'foo' => 'bar'
497
647
  end
498
648
 
499
- should "modify params hash by changing only GET" do
649
+ it "modify params hash by changing only GET" do
500
650
  e = Rack::MockRequest.env_for("?foo=duhget")
501
- req = Rack::Request.new(e)
502
- req.GET.should.equal 'foo' => 'duhget'
503
- req.POST.should.equal({})
651
+ req = make_request(e)
652
+ req.GET.must_equal 'foo' => 'duhget'
653
+ req.POST.must_equal({})
504
654
  req.update_param 'foo', 'bar'
505
- req.GET.should.equal 'foo' => 'bar'
506
- req.POST.should.equal({})
655
+ req.GET.must_equal 'foo' => 'bar'
656
+ req.POST.must_equal({})
507
657
  end
508
658
 
509
- should "modify params hash by changing only POST" do
659
+ it "modify params hash by changing only POST" do
510
660
  e = Rack::MockRequest.env_for("", "REQUEST_METHOD" => 'POST', :input => "foo=duhpost")
511
- req = Rack::Request.new(e)
512
- req.GET.should.equal({})
513
- req.POST.should.equal 'foo' => 'duhpost'
661
+ req = make_request(e)
662
+ req.GET.must_equal({})
663
+ req.POST.must_equal 'foo' => 'duhpost'
514
664
  req.update_param 'foo', 'bar'
515
- req.GET.should.equal({})
516
- req.POST.should.equal 'foo' => 'bar'
665
+ req.GET.must_equal({})
666
+ req.POST.must_equal 'foo' => 'bar'
517
667
  end
518
668
 
519
- should "modify params hash, even if param is defined in both POST and GET" do
669
+ it "modify params hash, even if param is defined in both POST and GET" do
520
670
  e = Rack::MockRequest.env_for("?foo=duhget", "REQUEST_METHOD" => 'POST', :input => "foo=duhpost")
521
- req1 = Rack::Request.new(e)
522
- req1.GET.should.equal 'foo' => 'duhget'
523
- req1.POST.should.equal 'foo' => 'duhpost'
524
- req1.params.should.equal 'foo' => 'duhpost'
671
+ req1 = make_request(e)
672
+ req1.GET.must_equal 'foo' => 'duhget'
673
+ req1.POST.must_equal 'foo' => 'duhpost'
674
+ req1.params.must_equal 'foo' => 'duhpost'
525
675
  req1.update_param 'foo', 'bar'
526
- req1.GET.should.equal 'foo' => 'bar'
527
- req1.POST.should.equal 'foo' => 'bar'
528
- req1.params.should.equal 'foo' => 'bar'
529
- req2 = Rack::Request.new(e)
530
- req2.GET.should.equal 'foo' => 'bar'
531
- req2.POST.should.equal 'foo' => 'bar'
532
- req2.params.should.equal 'foo' => 'bar'
533
- req2.params.should.equal 'foo' => 'bar'
676
+ req1.GET.must_equal 'foo' => 'bar'
677
+ req1.POST.must_equal 'foo' => 'bar'
678
+ req1.params.must_equal 'foo' => 'bar'
679
+ req2 = make_request(e)
680
+ req2.GET.must_equal 'foo' => 'bar'
681
+ req2.POST.must_equal 'foo' => 'bar'
682
+ req2.params.must_equal 'foo' => 'bar'
683
+ req2.params.must_equal 'foo' => 'bar'
534
684
  end
535
685
 
536
- should "allow deleting from params hash if param is in GET" do
686
+ it "allow deleting from params hash if param is in GET" do
537
687
  e = Rack::MockRequest.env_for("?foo=bar")
538
- req1 = Rack::Request.new(e)
539
- req1.params.should.equal 'foo' => 'bar'
540
- req1.delete_param('foo').should.equal 'bar'
541
- req1.params.should.equal({})
542
- req2 = Rack::Request.new(e)
543
- req2.params.should.equal({})
688
+ req1 = make_request(e)
689
+ req1.params.must_equal 'foo' => 'bar'
690
+ req1.delete_param('foo').must_equal 'bar'
691
+ req1.params.must_equal({})
692
+ req2 = make_request(e)
693
+ req2.params.must_equal({})
544
694
  end
545
695
 
546
- should "allow deleting from params hash if param is in POST" do
696
+ it "allow deleting from params hash if param is in POST" do
547
697
  e = Rack::MockRequest.env_for("", "REQUEST_METHOD" => 'POST', :input => 'foo=bar')
548
- req1 = Rack::Request.new(e)
549
- req1.params.should.equal 'foo' => 'bar'
550
- req1.delete_param('foo').should.equal 'bar'
551
- req1.params.should.equal({})
552
- req2 = Rack::Request.new(e)
553
- req2.params.should.equal({})
698
+ req1 = make_request(e)
699
+ req1.params.must_equal 'foo' => 'bar'
700
+ req1.delete_param('foo').must_equal 'bar'
701
+ req1.params.must_equal({})
702
+ req2 = make_request(e)
703
+ req2.params.must_equal({})
554
704
  end
555
705
 
556
- should "pass through non-uri escaped cookies as-is" do
557
- req = Rack::Request.new Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=%")
558
- req.cookies["foo"].should == "%"
706
+ it "pass through non-uri escaped cookies as-is" do
707
+ req = make_request Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=%")
708
+ req.cookies["foo"].must_equal "%"
559
709
  end
560
710
 
561
- should "parse cookies according to RFC 2109" do
562
- req = Rack::Request.new \
711
+ it "parse cookies according to RFC 2109" do
712
+ req = make_request \
563
713
  Rack::MockRequest.env_for('', 'HTTP_COOKIE' => 'foo=bar;foo=car')
564
- req.cookies.should.equal 'foo' => 'bar'
714
+ req.cookies.must_equal 'foo' => 'bar'
565
715
  end
566
716
 
567
- should 'parse cookies with quotes' do
568
- req = Rack::Request.new Rack::MockRequest.env_for('', {
717
+ it 'parse cookies with quotes' do
718
+ req = make_request Rack::MockRequest.env_for('', {
569
719
  'HTTP_COOKIE' => '$Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"; Part_Number="Rocket_Launcher_0001"; $Path="/acme"'
570
720
  })
571
- req.cookies.should.equal({
721
+ req.cookies.must_equal({
572
722
  '$Version' => '"1"',
573
723
  'Customer' => '"WILE_E_COYOTE"',
574
724
  '$Path' => '"/acme"',
@@ -576,88 +726,88 @@ describe Rack::Request do
576
726
  })
577
727
  end
578
728
 
579
- should "provide setters" do
580
- req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
581
- req.script_name.should.equal ""
729
+ it "provide setters" do
730
+ req = make_request(e=Rack::MockRequest.env_for(""))
731
+ req.script_name.must_equal ""
582
732
  req.script_name = "/foo"
583
- req.script_name.should.equal "/foo"
584
- e["SCRIPT_NAME"].should.equal "/foo"
733
+ req.script_name.must_equal "/foo"
734
+ e["SCRIPT_NAME"].must_equal "/foo"
585
735
 
586
- req.path_info.should.equal "/"
736
+ req.path_info.must_equal "/"
587
737
  req.path_info = "/foo"
588
- req.path_info.should.equal "/foo"
589
- e["PATH_INFO"].should.equal "/foo"
590
- end
591
-
592
- should "provide the original env" do
593
- req = Rack::Request.new(e = Rack::MockRequest.env_for(""))
594
- req.env.should == e
595
- end
596
-
597
- should "restore the base URL" do
598
- Rack::Request.new(Rack::MockRequest.env_for("")).base_url.
599
- should.equal "http://example.org"
600
- Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).base_url.
601
- should.equal "http://example.org"
602
- end
603
-
604
- should "restore the URL" do
605
- Rack::Request.new(Rack::MockRequest.env_for("")).url.
606
- should.equal "http://example.org/"
607
- Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).url.
608
- should.equal "http://example.org/foo/"
609
- Rack::Request.new(Rack::MockRequest.env_for("/foo")).url.
610
- should.equal "http://example.org/foo"
611
- Rack::Request.new(Rack::MockRequest.env_for("?foo")).url.
612
- should.equal "http://example.org/?foo"
613
- Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).url.
614
- should.equal "http://example.org:8080/"
615
- Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).url.
616
- should.equal "https://example.org/"
617
- Rack::Request.new(Rack::MockRequest.env_for("coffee://example.org/")).url.
618
- should.equal "coffee://example.org/"
619
- Rack::Request.new(Rack::MockRequest.env_for("coffee://example.org:443/")).url.
620
- should.equal "coffee://example.org:443/"
621
- Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).url.
622
- should.equal "https://example.com:8080/foo?foo"
623
- end
624
-
625
- should "restore the full path" do
626
- Rack::Request.new(Rack::MockRequest.env_for("")).fullpath.
627
- should.equal "/"
628
- Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).fullpath.
629
- should.equal "/foo/"
630
- Rack::Request.new(Rack::MockRequest.env_for("/foo")).fullpath.
631
- should.equal "/foo"
632
- Rack::Request.new(Rack::MockRequest.env_for("?foo")).fullpath.
633
- should.equal "/?foo"
634
- Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).fullpath.
635
- should.equal "/"
636
- Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).fullpath.
637
- should.equal "/"
638
-
639
- Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).fullpath.
640
- should.equal "/foo?foo"
641
- end
642
-
643
- should "handle multiple media type parameters" do
644
- req = Rack::Request.new \
738
+ req.path_info.must_equal "/foo"
739
+ e["PATH_INFO"].must_equal "/foo"
740
+ end
741
+
742
+ it "provide the original env" do
743
+ req = make_request(e = Rack::MockRequest.env_for(""))
744
+ req.env.must_equal e
745
+ end
746
+
747
+ it "restore the base URL" do
748
+ make_request(Rack::MockRequest.env_for("")).base_url.
749
+ must_equal "http://example.org"
750
+ make_request(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).base_url.
751
+ must_equal "http://example.org"
752
+ end
753
+
754
+ it "restore the URL" do
755
+ make_request(Rack::MockRequest.env_for("")).url.
756
+ must_equal "http://example.org/"
757
+ make_request(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).url.
758
+ must_equal "http://example.org/foo/"
759
+ make_request(Rack::MockRequest.env_for("/foo")).url.
760
+ must_equal "http://example.org/foo"
761
+ make_request(Rack::MockRequest.env_for("?foo")).url.
762
+ must_equal "http://example.org/?foo"
763
+ make_request(Rack::MockRequest.env_for("http://example.org:8080/")).url.
764
+ must_equal "http://example.org:8080/"
765
+ make_request(Rack::MockRequest.env_for("https://example.org/")).url.
766
+ must_equal "https://example.org/"
767
+ make_request(Rack::MockRequest.env_for("coffee://example.org/")).url.
768
+ must_equal "coffee://example.org/"
769
+ make_request(Rack::MockRequest.env_for("coffee://example.org:443/")).url.
770
+ must_equal "coffee://example.org:443/"
771
+ make_request(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).url.
772
+ must_equal "https://example.com:8080/foo?foo"
773
+ end
774
+
775
+ it "restore the full path" do
776
+ make_request(Rack::MockRequest.env_for("")).fullpath.
777
+ must_equal "/"
778
+ make_request(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).fullpath.
779
+ must_equal "/foo/"
780
+ make_request(Rack::MockRequest.env_for("/foo")).fullpath.
781
+ must_equal "/foo"
782
+ make_request(Rack::MockRequest.env_for("?foo")).fullpath.
783
+ must_equal "/?foo"
784
+ make_request(Rack::MockRequest.env_for("http://example.org:8080/")).fullpath.
785
+ must_equal "/"
786
+ make_request(Rack::MockRequest.env_for("https://example.org/")).fullpath.
787
+ must_equal "/"
788
+
789
+ make_request(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).fullpath.
790
+ must_equal "/foo?foo"
791
+ end
792
+
793
+ it "handle multiple media type parameters" do
794
+ req = make_request \
645
795
  Rack::MockRequest.env_for("/",
646
796
  "CONTENT_TYPE" => 'text/plain; foo=BAR,baz=bizzle dizzle;BLING=bam;blong="boo";zump="zoo\"o";weird=lol"')
647
- req.should.not.be.form_data
648
- req.media_type_params.should.include 'foo'
649
- req.media_type_params['foo'].should.equal 'BAR'
650
- req.media_type_params.should.include 'baz'
651
- req.media_type_params['baz'].should.equal 'bizzle dizzle'
652
- req.media_type_params.should.not.include 'BLING'
653
- req.media_type_params.should.include 'bling'
654
- req.media_type_params['bling'].should.equal 'bam'
655
- req.media_type_params['blong'].should.equal 'boo'
656
- req.media_type_params['zump'].should.equal 'zoo\"o'
657
- req.media_type_params['weird'].should.equal 'lol"'
658
- end
659
-
660
- should "parse with junk before boundry" do
797
+ req.wont_be :form_data?
798
+ req.media_type_params.must_include 'foo'
799
+ req.media_type_params['foo'].must_equal 'BAR'
800
+ req.media_type_params.must_include 'baz'
801
+ req.media_type_params['baz'].must_equal 'bizzle dizzle'
802
+ req.media_type_params.wont_include 'BLING'
803
+ req.media_type_params.must_include 'bling'
804
+ req.media_type_params['bling'].must_equal 'bam'
805
+ req.media_type_params['blong'].must_equal 'boo'
806
+ req.media_type_params['zump'].must_equal 'zoo\"o'
807
+ req.media_type_params['weird'].must_equal 'lol"'
808
+ end
809
+
810
+ it "parse with junk before boundary" do
661
811
  # Adapted from RFC 1867.
662
812
  input = <<EOF
663
813
  blah blah\r
@@ -674,31 +824,31 @@ Content-Transfer-Encoding: base64\r
674
824
  /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
675
825
  --AaB03x--\r
676
826
  EOF
677
- req = Rack::Request.new Rack::MockRequest.env_for("/",
827
+ req = make_request Rack::MockRequest.env_for("/",
678
828
  "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
679
829
  "CONTENT_LENGTH" => input.size,
680
830
  :input => input)
681
831
 
682
- req.POST.should.include "fileupload"
683
- req.POST.should.include "reply"
832
+ req.POST.must_include "fileupload"
833
+ req.POST.must_include "reply"
684
834
 
685
- req.should.be.form_data
686
- req.content_length.should.equal input.size
687
- req.media_type.should.equal 'multipart/form-data'
688
- req.media_type_params.should.include 'boundary'
689
- req.media_type_params['boundary'].should.equal 'AaB03x'
835
+ req.must_be :form_data?
836
+ req.content_length.must_equal input.size
837
+ req.media_type.must_equal 'multipart/form-data'
838
+ req.media_type_params.must_include 'boundary'
839
+ req.media_type_params['boundary'].must_equal 'AaB03x'
690
840
 
691
- req.POST["reply"].should.equal "yes"
841
+ req.POST["reply"].must_equal "yes"
692
842
 
693
843
  f = req.POST["fileupload"]
694
- f.should.be.kind_of Hash
695
- f[:type].should.equal "image/jpeg"
696
- f[:filename].should.equal "dj.jpg"
697
- f.should.include :tempfile
698
- f[:tempfile].size.should.equal 76
844
+ f.must_be_kind_of Hash
845
+ f[:type].must_equal "image/jpeg"
846
+ f[:filename].must_equal "dj.jpg"
847
+ f.must_include :tempfile
848
+ f[:tempfile].size.must_equal 76
699
849
  end
700
850
 
701
- should "not infinite loop with a malformed HTTP request" do
851
+ it "not infinite loop with a malformed HTTP request" do
702
852
  # Adapted from RFC 1867.
703
853
  input = <<EOF
704
854
  --AaB03x
@@ -713,16 +863,16 @@ Content-Transfer-Encoding: base64
713
863
  /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg
714
864
  --AaB03x--
715
865
  EOF
716
- req = Rack::Request.new Rack::MockRequest.env_for("/",
866
+ req = make_request Rack::MockRequest.env_for("/",
717
867
  "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
718
868
  "CONTENT_LENGTH" => input.size,
719
869
  :input => input)
720
870
 
721
- lambda{req.POST}.should.raise(EOFError)
871
+ lambda{req.POST}.must_raise EOFError
722
872
  end
723
873
 
724
874
 
725
- should "parse multipart form data" do
875
+ it "parse multipart form data" do
726
876
  # Adapted from RFC 1867.
727
877
  input = <<EOF
728
878
  --AaB03x\r
@@ -737,47 +887,89 @@ Content-Transfer-Encoding: base64\r
737
887
  /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
738
888
  --AaB03x--\r
739
889
  EOF
740
- req = Rack::Request.new Rack::MockRequest.env_for("/",
890
+ req = make_request Rack::MockRequest.env_for("/",
741
891
  "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
742
892
  "CONTENT_LENGTH" => input.size,
743
893
  :input => input)
744
894
 
745
- req.POST.should.include "fileupload"
746
- req.POST.should.include "reply"
895
+ req.POST.must_include "fileupload"
896
+ req.POST.must_include "reply"
747
897
 
748
- req.should.be.form_data
749
- req.content_length.should.equal input.size
750
- req.media_type.should.equal 'multipart/form-data'
751
- req.media_type_params.should.include 'boundary'
752
- req.media_type_params['boundary'].should.equal 'AaB03x'
898
+ req.must_be :form_data?
899
+ req.content_length.must_equal input.size
900
+ req.media_type.must_equal 'multipart/form-data'
901
+ req.media_type_params.must_include 'boundary'
902
+ req.media_type_params['boundary'].must_equal 'AaB03x'
753
903
 
754
- req.POST["reply"].should.equal "yes"
904
+ req.POST["reply"].must_equal "yes"
755
905
 
756
906
  f = req.POST["fileupload"]
757
- f.should.be.kind_of Hash
758
- f[:type].should.equal "image/jpeg"
759
- f[:filename].should.equal "dj.jpg"
760
- f.should.include :tempfile
761
- f[:tempfile].size.should.equal 76
907
+ f.must_be_kind_of Hash
908
+ f[:type].must_equal "image/jpeg"
909
+ f[:filename].must_equal "dj.jpg"
910
+ f.must_include :tempfile
911
+ f[:tempfile].size.must_equal 76
912
+ end
913
+
914
+ it "MultipartPartLimitError when request has too many multipart file parts if limit set" do
915
+ begin
916
+ data = 10000.times.map { "--AaB03x\r\nContent-Type: text/plain\r\nContent-Disposition: attachment; name=#{SecureRandom.hex(10)}; filename=#{SecureRandom.hex(10)}\r\n\r\ncontents\r\n" }.join("\r\n")
917
+ data += "--AaB03x--\r"
918
+
919
+ options = {
920
+ "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
921
+ "CONTENT_LENGTH" => data.length.to_s,
922
+ :input => StringIO.new(data)
923
+ }
924
+
925
+ request = make_request Rack::MockRequest.env_for("/", options)
926
+ lambda { request.POST }.must_raise Rack::Multipart::MultipartPartLimitError
927
+ end
928
+ end
929
+
930
+ it "MultipartPartLimitError when request has too many multipart total parts if limit set" do
931
+ begin
932
+ data = 10000.times.map { "--AaB03x\r\ncontent-type: text/plain\r\ncontent-disposition: attachment; name=#{SecureRandom.hex(10)}\r\n\r\ncontents\r\n" }.join("\r\n")
933
+ data += "--AaB03x--\r"
934
+
935
+ options = {
936
+ "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
937
+ "CONTENT_LENGTH" => data.length.to_s,
938
+ :input => StringIO.new(data)
939
+ }
940
+
941
+ request = make_request Rack::MockRequest.env_for("/", options)
942
+ lambda { request.POST }.must_raise Rack::Multipart::MultipartTotalPartLimitError
943
+ end
762
944
  end
763
945
 
764
- should "MultipartPartLimitError when request has too many multipart parts if limit set" do
946
+ it 'closes tempfiles it created in the case of too many created' do
765
947
  begin
766
948
  data = 10000.times.map { "--AaB03x\r\nContent-Type: text/plain\r\nContent-Disposition: attachment; name=#{SecureRandom.hex(10)}; filename=#{SecureRandom.hex(10)}\r\n\r\ncontents\r\n" }.join("\r\n")
767
949
  data += "--AaB03x--\r"
768
950
 
951
+ files = []
769
952
  options = {
770
953
  "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
771
954
  "CONTENT_LENGTH" => data.length.to_s,
955
+ Rack::RACK_MULTIPART_TEMPFILE_FACTORY => lambda { |filename, content_type|
956
+ file = Tempfile.new(["RackMultipart", ::File.extname(filename)])
957
+ files << file
958
+ file
959
+ },
772
960
  :input => StringIO.new(data)
773
961
  }
774
962
 
775
- request = Rack::Request.new Rack::MockRequest.env_for("/", options)
776
- lambda { request.POST }.should.raise(Rack::Multipart::MultipartPartLimitError)
963
+ request = make_request Rack::MockRequest.env_for("/", options)
964
+ assert_raises(Rack::Multipart::MultipartPartLimitError) do
965
+ request.POST
966
+ end
967
+ refute_predicate files, :empty?
968
+ files.each { |f| assert_predicate f, :closed? }
777
969
  end
778
970
  end
779
971
 
780
- should "parse big multipart form data" do
972
+ it "parse big multipart form data" do
781
973
  input = <<EOF
782
974
  --AaB03x\r
783
975
  content-disposition: form-data; name="huge"; filename="huge"\r
@@ -789,17 +981,17 @@ content-disposition: form-data; name="mean"; filename="mean"\r
789
981
  --AaB03xha\r
790
982
  --AaB03x--\r
791
983
  EOF
792
- req = Rack::Request.new Rack::MockRequest.env_for("/",
984
+ req = make_request Rack::MockRequest.env_for("/",
793
985
  "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
794
986
  "CONTENT_LENGTH" => input.size,
795
987
  :input => input)
796
988
 
797
- req.POST["huge"][:tempfile].size.should.equal 32768
798
- req.POST["mean"][:tempfile].size.should.equal 10
799
- req.POST["mean"][:tempfile].read.should.equal "--AaB03xha"
989
+ req.POST["huge"][:tempfile].size.must_equal 32768
990
+ req.POST["mean"][:tempfile].size.must_equal 10
991
+ req.POST["mean"][:tempfile].read.must_equal "--AaB03xha"
800
992
  end
801
993
 
802
- should "record tempfiles from multipart form data in env[rack.tempfiles]" do
994
+ it "record tempfiles from multipart form data in env[rack.tempfiles]" do
803
995
  input = <<EOF
804
996
  --AaB03x\r
805
997
  content-disposition: form-data; name="fileupload"; filename="foo.jpg"\r
@@ -819,22 +1011,22 @@ EOF
819
1011
  "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
820
1012
  "CONTENT_LENGTH" => input.size,
821
1013
  :input => input)
822
- req = Rack::Request.new(env)
1014
+ req = make_request(env)
823
1015
  req.params
824
- env['rack.tempfiles'].size.should.equal(2)
1016
+ env['rack.tempfiles'].size.must_equal 2
825
1017
  end
826
1018
 
827
- should "detect invalid multipart form data" do
1019
+ it "detect invalid multipart form data" do
828
1020
  input = <<EOF
829
1021
  --AaB03x\r
830
1022
  content-disposition: form-data; name="huge"; filename="huge"\r
831
1023
  EOF
832
- req = Rack::Request.new Rack::MockRequest.env_for("/",
1024
+ req = make_request Rack::MockRequest.env_for("/",
833
1025
  "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
834
1026
  "CONTENT_LENGTH" => input.size,
835
1027
  :input => input)
836
1028
 
837
- lambda { req.POST }.should.raise(EOFError)
1029
+ lambda { req.POST }.must_raise EOFError
838
1030
 
839
1031
  input = <<EOF
840
1032
  --AaB03x\r
@@ -842,12 +1034,12 @@ content-disposition: form-data; name="huge"; filename="huge"\r
842
1034
  \r
843
1035
  foo\r
844
1036
  EOF
845
- req = Rack::Request.new Rack::MockRequest.env_for("/",
1037
+ req = make_request Rack::MockRequest.env_for("/",
846
1038
  "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
847
1039
  "CONTENT_LENGTH" => input.size,
848
1040
  :input => input)
849
1041
 
850
- lambda { req.POST }.should.raise(EOFError)
1042
+ lambda { req.POST }.must_raise EOFError
851
1043
 
852
1044
  input = <<EOF
853
1045
  --AaB03x\r
@@ -855,29 +1047,29 @@ content-disposition: form-data; name="huge"; filename="huge"\r
855
1047
  \r
856
1048
  foo\r
857
1049
  EOF
858
- req = Rack::Request.new Rack::MockRequest.env_for("/",
1050
+ req = make_request Rack::MockRequest.env_for("/",
859
1051
  "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
860
1052
  "CONTENT_LENGTH" => input.size,
861
1053
  :input => input)
862
1054
 
863
- lambda { req.POST }.should.raise(EOFError)
1055
+ lambda { req.POST }.must_raise EOFError
864
1056
  end
865
1057
 
866
- should "consistently raise EOFError on bad multipart form data" do
1058
+ it "consistently raise EOFError on bad multipart form data" do
867
1059
  input = <<EOF
868
1060
  --AaB03x\r
869
1061
  content-disposition: form-data; name="huge"; filename="huge"\r
870
1062
  EOF
871
- req = Rack::Request.new Rack::MockRequest.env_for("/",
1063
+ req = make_request Rack::MockRequest.env_for("/",
872
1064
  "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
873
1065
  "CONTENT_LENGTH" => input.size,
874
1066
  :input => input)
875
1067
 
876
- lambda { req.POST }.should.raise(EOFError)
877
- lambda { req.POST }.should.raise(EOFError)
1068
+ lambda { req.POST }.must_raise EOFError
1069
+ lambda { req.POST }.must_raise EOFError
878
1070
  end
879
1071
 
880
- should "correctly parse the part name from Content-Id header" do
1072
+ it "correctly parse the part name from Content-Id header" do
881
1073
  input = <<EOF
882
1074
  --AaB03x\r
883
1075
  Content-Type: text/xml; charset=utf-8\r
@@ -887,20 +1079,15 @@ Content-Transfer-Encoding: 7bit\r
887
1079
  foo\r
888
1080
  --AaB03x--\r
889
1081
  EOF
890
- req = Rack::Request.new Rack::MockRequest.env_for("/",
1082
+ req = make_request Rack::MockRequest.env_for("/",
891
1083
  "CONTENT_TYPE" => "multipart/related, boundary=AaB03x",
892
1084
  "CONTENT_LENGTH" => input.size,
893
1085
  :input => input)
894
1086
 
895
- req.params.keys.should.equal ["<soap-start>"]
1087
+ req.params.keys.must_equal ["<soap-start>"]
896
1088
  end
897
1089
 
898
- should "not try to interpret binary as utf8" do
899
- if /regexp/.respond_to?(:kcode) # < 1.9
900
- begin
901
- original_kcode = $KCODE
902
- $KCODE='UTF8'
903
-
1090
+ it "not try to interpret binary as utf8" do
904
1091
  input = <<EOF
905
1092
  --AaB03x\r
906
1093
  content-disposition: form-data; name="fileupload"; filename="junk.a"\r
@@ -910,77 +1097,33 @@ content-type: application/octet-stream\r
910
1097
  --AaB03x--\r
911
1098
  EOF
912
1099
 
913
- req = Rack::Request.new Rack::MockRequest.env_for("/",
1100
+ req = make_request Rack::MockRequest.env_for("/",
914
1101
  "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
915
1102
  "CONTENT_LENGTH" => input.size,
916
1103
  :input => input)
917
1104
 
918
- lambda{req.POST}.should.not.raise(EOFError)
919
- req.POST["fileupload"][:tempfile].size.should.equal 4
920
- ensure
921
- $KCODE = original_kcode
922
- end
923
- else # >= 1.9
924
- input = <<EOF
925
- --AaB03x\r
926
- content-disposition: form-data; name="fileupload"; filename="junk.a"\r
927
- content-type: application/octet-stream\r
928
- \r
929
- #{[0x36,0xCF,0x0A,0xF8].pack('c*')}\r
930
- --AaB03x--\r
931
- EOF
932
-
933
- req = Rack::Request.new Rack::MockRequest.env_for("/",
934
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
935
- "CONTENT_LENGTH" => input.size,
936
- :input => input)
937
-
938
- lambda{req.POST}.should.not.raise(EOFError)
939
- req.POST["fileupload"][:tempfile].size.should.equal 4
940
- end
1105
+ req.POST["fileupload"][:tempfile].size.must_equal 4
941
1106
  end
942
1107
 
943
- should "work around buggy 1.8.* Tempfile equality" do
944
- input = <<EOF
945
- --AaB03x\r
946
- content-disposition: form-data; name="huge"; filename="huge"\r
947
- \r
948
- foo\r
949
- --AaB03x--
950
- EOF
951
-
952
- rack_input = Tempfile.new("rackspec")
953
- rack_input.write(input)
954
- rack_input.rewind
955
-
956
- req = Rack::Request.new Rack::MockRequest.env_for("/",
957
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
958
- "CONTENT_LENGTH" => input.size,
959
- :input => rack_input)
960
-
961
- lambda{ req.POST }.should.not.raise
962
- lambda{ req.POST }.should.not.raise("input re-processed!")
963
- end
964
-
965
- should "use form_hash when form_input is a Tempfile" do
1108
+ it "use form_hash when form_input is a Tempfile" do
966
1109
  input = "{foo: 'bar'}"
967
1110
 
968
1111
  rack_input = Tempfile.new("rackspec")
969
1112
  rack_input.write(input)
970
1113
  rack_input.rewind
971
1114
 
972
- req = Rack::Request.new Rack::MockRequest.env_for("/",
1115
+ req = make_request Rack::MockRequest.env_for("/",
973
1116
  "rack.request.form_hash" => {'foo' => 'bar'},
974
1117
  "rack.request.form_input" => rack_input,
975
1118
  :input => rack_input)
976
1119
 
977
- req.POST.should.equal(req.env['rack.request.form_hash'])
1120
+ req.POST.must_equal req.env['rack.request.form_hash']
978
1121
  end
979
1122
 
980
- should "conform to the Rack spec" do
1123
+ it "conform to the Rack spec" do
981
1124
  app = lambda { |env|
982
- content = Rack::Request.new(env).POST["file"].inspect
983
- size = content.respond_to?(:bytesize) ? content.bytesize : content.size
1125
+ content = make_request(env).POST["file"].inspect
1126
+ size = content.bytesize
984
1127
  [200, {"Content-Type" => "text/html", "Content-Length" => size.to_s}, [content]]
985
1128
  }
986
1129
 
@@ -997,149 +1140,151 @@ Content-Transfer-Encoding: base64\r
997
1140
  /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
998
1141
  --AaB03x--\r
999
1142
  EOF
1000
- input.force_encoding("ASCII-8BIT") if input.respond_to? :force_encoding
1143
+ input.force_encoding(Encoding::ASCII_8BIT)
1001
1144
  res = Rack::MockRequest.new(Rack::Lint.new(app)).get "/",
1002
1145
  "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
1003
1146
  "CONTENT_LENGTH" => input.size.to_s, "rack.input" => StringIO.new(input)
1004
1147
 
1005
- res.should.be.ok
1148
+ res.must_be :ok?
1006
1149
  end
1007
1150
 
1008
- should "parse Accept-Encoding correctly" do
1151
+ it "parse Accept-Encoding correctly" do
1009
1152
  parser = lambda do |x|
1010
- Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => x)).accept_encoding
1153
+ make_request(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => x)).accept_encoding
1011
1154
  end
1012
1155
 
1013
- parser.call(nil).should.equal([])
1156
+ parser.call(nil).must_equal []
1014
1157
 
1015
- parser.call("compress, gzip").should.equal([["compress", 1.0], ["gzip", 1.0]])
1016
- parser.call("").should.equal([])
1017
- parser.call("*").should.equal([["*", 1.0]])
1018
- parser.call("compress;q=0.5, gzip;q=1.0").should.equal([["compress", 0.5], ["gzip", 1.0]])
1019
- parser.call("gzip;q=1.0, identity; q=0.5, *;q=0").should.equal([["gzip", 1.0], ["identity", 0.5], ["*", 0] ])
1158
+ parser.call("compress, gzip").must_equal [["compress", 1.0], ["gzip", 1.0]]
1159
+ parser.call("").must_equal []
1160
+ parser.call("*").must_equal [["*", 1.0]]
1161
+ parser.call("compress;q=0.5, gzip;q=1.0").must_equal [["compress", 0.5], ["gzip", 1.0]]
1162
+ parser.call("gzip;q=1.0, identity; q=0.5, *;q=0").must_equal [["gzip", 1.0], ["identity", 0.5], ["*", 0] ]
1020
1163
 
1021
- parser.call("gzip ; q=0.9").should.equal([["gzip", 0.9]])
1022
- parser.call("gzip ; deflate").should.equal([["gzip", 1.0]])
1164
+ parser.call("gzip ; q=0.9").must_equal [["gzip", 0.9]]
1165
+ parser.call("gzip ; deflate").must_equal [["gzip", 1.0]]
1023
1166
  end
1024
1167
 
1025
- should "parse Accept-Language correctly" do
1168
+ it "parse Accept-Language correctly" do
1026
1169
  parser = lambda do |x|
1027
- Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_LANGUAGE" => x)).accept_language
1170
+ make_request(Rack::MockRequest.env_for("", "HTTP_ACCEPT_LANGUAGE" => x)).accept_language
1028
1171
  end
1029
1172
 
1030
- parser.call(nil).should.equal([])
1173
+ parser.call(nil).must_equal []
1031
1174
 
1032
- parser.call("fr, en").should.equal([["fr", 1.0], ["en", 1.0]])
1033
- parser.call("").should.equal([])
1034
- parser.call("*").should.equal([["*", 1.0]])
1035
- parser.call("fr;q=0.5, en;q=1.0").should.equal([["fr", 0.5], ["en", 1.0]])
1036
- parser.call("fr;q=1.0, en; q=0.5, *;q=0").should.equal([["fr", 1.0], ["en", 0.5], ["*", 0] ])
1175
+ parser.call("fr, en").must_equal [["fr", 1.0], ["en", 1.0]]
1176
+ parser.call("").must_equal []
1177
+ parser.call("*").must_equal [["*", 1.0]]
1178
+ parser.call("fr;q=0.5, en;q=1.0").must_equal [["fr", 0.5], ["en", 1.0]]
1179
+ parser.call("fr;q=1.0, en; q=0.5, *;q=0").must_equal [["fr", 1.0], ["en", 0.5], ["*", 0] ]
1037
1180
 
1038
- parser.call("fr ; q=0.9").should.equal([["fr", 0.9]])
1039
- parser.call("fr").should.equal([["fr", 1.0]])
1181
+ parser.call("fr ; q=0.9").must_equal [["fr", 0.9]]
1182
+ parser.call("fr").must_equal [["fr", 1.0]]
1040
1183
  end
1041
1184
 
1042
- ip_app = lambda { |env|
1043
- request = Rack::Request.new(env)
1044
- response = Rack::Response.new
1045
- response.write request.ip
1046
- response.finish
1047
- }
1185
+ def ip_app
1186
+ lambda { |env|
1187
+ request = make_request(env)
1188
+ response = Rack::Response.new
1189
+ response.write request.ip
1190
+ response.finish
1191
+ }
1192
+ end
1048
1193
 
1049
- should 'provide ip information' do
1194
+ it 'provide ip information' do
1050
1195
  mock = Rack::MockRequest.new(Rack::Lint.new(ip_app))
1051
1196
 
1052
1197
  res = mock.get '/', 'REMOTE_ADDR' => '1.2.3.4'
1053
- res.body.should.equal '1.2.3.4'
1198
+ res.body.must_equal '1.2.3.4'
1054
1199
 
1055
1200
  res = mock.get '/', 'REMOTE_ADDR' => 'fe80::202:b3ff:fe1e:8329'
1056
- res.body.should.equal 'fe80::202:b3ff:fe1e:8329'
1201
+ res.body.must_equal 'fe80::202:b3ff:fe1e:8329'
1057
1202
 
1058
1203
  res = mock.get '/', 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6'
1059
- res.body.should.equal '1.2.3.4'
1204
+ res.body.must_equal '1.2.3.4'
1060
1205
  end
1061
1206
 
1062
- should 'deals with proxies' do
1207
+ it 'deals with proxies' do
1063
1208
  mock = Rack::MockRequest.new(Rack::Lint.new(ip_app))
1064
1209
 
1065
1210
  res = mock.get '/',
1066
1211
  'REMOTE_ADDR' => '1.2.3.4',
1067
1212
  'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
1068
- res.body.should.equal '1.2.3.4'
1213
+ res.body.must_equal '1.2.3.4'
1069
1214
 
1070
1215
  res = mock.get '/',
1071
1216
  'REMOTE_ADDR' => '1.2.3.4',
1072
1217
  'HTTP_X_FORWARDED_FOR' => 'unknown'
1073
- res.body.should.equal '1.2.3.4'
1218
+ res.body.must_equal '1.2.3.4'
1074
1219
 
1075
1220
  res = mock.get '/',
1076
1221
  'REMOTE_ADDR' => '127.0.0.1',
1077
1222
  'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
1078
- res.body.should.equal '3.4.5.6'
1223
+ res.body.must_equal '3.4.5.6'
1079
1224
 
1080
1225
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'unknown,3.4.5.6'
1081
- res.body.should.equal '3.4.5.6'
1226
+ res.body.must_equal '3.4.5.6'
1082
1227
 
1083
1228
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '192.168.0.1,3.4.5.6'
1084
- res.body.should.equal '3.4.5.6'
1229
+ res.body.must_equal '3.4.5.6'
1085
1230
 
1086
1231
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '10.0.0.1,3.4.5.6'
1087
- res.body.should.equal '3.4.5.6'
1232
+ res.body.must_equal '3.4.5.6'
1088
1233
 
1089
1234
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '10.0.0.1, 10.0.0.1, 3.4.5.6'
1090
- res.body.should.equal '3.4.5.6'
1235
+ res.body.must_equal '3.4.5.6'
1091
1236
 
1092
1237
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '127.0.0.1, 3.4.5.6'
1093
- res.body.should.equal '3.4.5.6'
1238
+ res.body.must_equal '3.4.5.6'
1094
1239
 
1095
1240
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'unknown,192.168.0.1'
1096
- res.body.should.equal 'unknown'
1241
+ res.body.must_equal 'unknown'
1097
1242
 
1098
1243
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'other,unknown,192.168.0.1'
1099
- res.body.should.equal 'unknown'
1244
+ res.body.must_equal 'unknown'
1100
1245
 
1101
1246
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'unknown,localhost,192.168.0.1'
1102
- res.body.should.equal 'unknown'
1247
+ res.body.must_equal 'unknown'
1103
1248
 
1104
1249
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 10.0.0.1, 172.31.4.4'
1105
- res.body.should.equal '3.4.5.6'
1250
+ res.body.must_equal '3.4.5.6'
1106
1251
 
1107
1252
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '::1,2620:0:1c00:0:812c:9583:754b:ca11'
1108
- res.body.should.equal '2620:0:1c00:0:812c:9583:754b:ca11'
1253
+ res.body.must_equal '2620:0:1c00:0:812c:9583:754b:ca11'
1109
1254
 
1110
1255
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '2620:0:1c00:0:812c:9583:754b:ca11,::1'
1111
- res.body.should.equal '2620:0:1c00:0:812c:9583:754b:ca11'
1256
+ res.body.must_equal '2620:0:1c00:0:812c:9583:754b:ca11'
1112
1257
 
1113
1258
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'fd5b:982e:9130:247f:0000:0000:0000:0000,2620:0:1c00:0:812c:9583:754b:ca11'
1114
- res.body.should.equal '2620:0:1c00:0:812c:9583:754b:ca11'
1259
+ res.body.must_equal '2620:0:1c00:0:812c:9583:754b:ca11'
1115
1260
 
1116
1261
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '2620:0:1c00:0:812c:9583:754b:ca11,fd5b:982e:9130:247f:0000:0000:0000:0000'
1117
- res.body.should.equal '2620:0:1c00:0:812c:9583:754b:ca11'
1262
+ res.body.must_equal '2620:0:1c00:0:812c:9583:754b:ca11'
1118
1263
 
1119
1264
  res = mock.get '/',
1120
1265
  'HTTP_X_FORWARDED_FOR' => '1.1.1.1, 127.0.0.1',
1121
1266
  'HTTP_CLIENT_IP' => '1.1.1.1'
1122
- res.body.should.equal '1.1.1.1'
1267
+ res.body.must_equal '1.1.1.1'
1123
1268
 
1124
1269
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '8.8.8.8, 9.9.9.9'
1125
- res.body.should.equal '9.9.9.9'
1270
+ res.body.must_equal '9.9.9.9'
1126
1271
 
1127
1272
  res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '8.8.8.8, fe80::202:b3ff:fe1e:8329'
1128
- res.body.should.equal 'fe80::202:b3ff:fe1e:8329'
1273
+ res.body.must_equal 'fe80::202:b3ff:fe1e:8329'
1129
1274
 
1130
1275
  # Unix Sockets
1131
1276
  res = mock.get '/',
1132
1277
  'REMOTE_ADDR' => 'unix',
1133
1278
  'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
1134
- res.body.should.equal '3.4.5.6'
1279
+ res.body.must_equal '3.4.5.6'
1135
1280
 
1136
1281
  res = mock.get '/',
1137
1282
  'REMOTE_ADDR' => 'unix:/tmp/foo',
1138
1283
  'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
1139
- res.body.should.equal '3.4.5.6'
1284
+ res.body.must_equal '3.4.5.6'
1140
1285
  end
1141
1286
 
1142
- should "not allow IP spoofing via Client-IP and X-Forwarded-For headers" do
1287
+ it "not allow IP spoofing via Client-IP and X-Forwarded-For headers" do
1143
1288
  mock = Rack::MockRequest.new(Rack::Lint.new(ip_app))
1144
1289
 
1145
1290
  # IP Spoofing attempt:
@@ -1154,31 +1299,45 @@ EOF
1154
1299
  res = mock.get '/',
1155
1300
  'HTTP_X_FORWARDED_FOR' => '6.6.6.6, 2.2.2.3, 192.168.0.7',
1156
1301
  'HTTP_CLIENT_IP' => '6.6.6.6'
1157
- res.body.should.equal '2.2.2.3'
1158
- end
1159
-
1160
- should "regard local addresses as proxies" do
1161
- req = Rack::Request.new(Rack::MockRequest.env_for("/"))
1162
- req.trusted_proxy?('127.0.0.1').should.equal 0
1163
- req.trusted_proxy?('10.0.0.1').should.equal 0
1164
- req.trusted_proxy?('172.16.0.1').should.equal 0
1165
- req.trusted_proxy?('172.20.0.1').should.equal 0
1166
- req.trusted_proxy?('172.30.0.1').should.equal 0
1167
- req.trusted_proxy?('172.31.0.1').should.equal 0
1168
- req.trusted_proxy?('192.168.0.1').should.equal 0
1169
- req.trusted_proxy?('::1').should.equal 0
1170
- req.trusted_proxy?('fd00::').should.equal 0
1171
- req.trusted_proxy?('localhost').should.equal 0
1172
- req.trusted_proxy?('unix').should.equal 0
1173
- req.trusted_proxy?('unix:/tmp/sock').should.equal 0
1174
-
1175
- req.trusted_proxy?("unix.example.org").should.equal nil
1176
- req.trusted_proxy?("example.org\n127.0.0.1").should.equal nil
1177
- req.trusted_proxy?("127.0.0.1\nexample.org").should.equal nil
1178
- req.trusted_proxy?("11.0.0.1").should.equal nil
1179
- req.trusted_proxy?("172.15.0.1").should.equal nil
1180
- req.trusted_proxy?("172.32.0.1").should.equal nil
1181
- req.trusted_proxy?("2001:470:1f0b:18f8::1").should.equal nil
1302
+ res.body.must_equal '2.2.2.3'
1303
+ end
1304
+
1305
+ it "preserves ip for trusted proxy chain" do
1306
+ mock = Rack::MockRequest.new(Rack::Lint.new(ip_app))
1307
+ res = mock.get '/',
1308
+ 'HTTP_X_FORWARDED_FOR' => '192.168.0.11, 192.168.0.7',
1309
+ 'HTTP_CLIENT_IP' => '127.0.0.1'
1310
+ res.body.must_equal '192.168.0.11'
1311
+
1312
+ end
1313
+
1314
+ it "regards local addresses as proxies" do
1315
+ req = make_request(Rack::MockRequest.env_for("/"))
1316
+ req.trusted_proxy?('127.0.0.1').must_equal 0
1317
+ req.trusted_proxy?('10.0.0.1').must_equal 0
1318
+ req.trusted_proxy?('172.16.0.1').must_equal 0
1319
+ req.trusted_proxy?('172.20.0.1').must_equal 0
1320
+ req.trusted_proxy?('172.30.0.1').must_equal 0
1321
+ req.trusted_proxy?('172.31.0.1').must_equal 0
1322
+ req.trusted_proxy?('192.168.0.1').must_equal 0
1323
+ req.trusted_proxy?('::1').must_equal 0
1324
+ req.trusted_proxy?('fd00::').must_equal 0
1325
+ req.trusted_proxy?('localhost').must_equal 0
1326
+ req.trusted_proxy?('unix').must_equal 0
1327
+ req.trusted_proxy?('unix:/tmp/sock').must_equal 0
1328
+
1329
+ req.trusted_proxy?("unix.example.org").must_be_nil
1330
+ req.trusted_proxy?("example.org\n127.0.0.1").must_be_nil
1331
+ req.trusted_proxy?("127.0.0.1\nexample.org").must_be_nil
1332
+ req.trusted_proxy?("11.0.0.1").must_be_nil
1333
+ req.trusted_proxy?("172.15.0.1").must_be_nil
1334
+ req.trusted_proxy?("172.32.0.1").must_be_nil
1335
+ req.trusted_proxy?("2001:470:1f0b:18f8::1").must_be_nil
1336
+ end
1337
+
1338
+ it "sets the default session to an empty hash" do
1339
+ req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
1340
+ assert_equal Hash.new, req.session
1182
1341
  end
1183
1342
 
1184
1343
  class MyRequest < Rack::Request
@@ -1187,46 +1346,78 @@ EOF
1187
1346
  end
1188
1347
  end
1189
1348
 
1190
- should "allow subclass request to be instantiated after parent request" do
1349
+ it "allow subclass request to be instantiated after parent request" do
1191
1350
  env = Rack::MockRequest.env_for("/?foo=bar")
1192
1351
 
1193
- req1 = Rack::Request.new(env)
1194
- req1.GET.should.equal "foo" => "bar"
1195
- req1.params.should.equal "foo" => "bar"
1352
+ req1 = make_request(env)
1353
+ req1.GET.must_equal "foo" => "bar"
1354
+ req1.params.must_equal "foo" => "bar"
1196
1355
 
1197
1356
  req2 = MyRequest.new(env)
1198
- req2.GET.should.equal "foo" => "bar"
1199
- req2.params.should.equal :foo => "bar"
1357
+ req2.GET.must_equal "foo" => "bar"
1358
+ req2.params.must_equal :foo => "bar"
1200
1359
  end
1201
1360
 
1202
- should "allow parent request to be instantiated after subclass request" do
1361
+ it "allow parent request to be instantiated after subclass request" do
1203
1362
  env = Rack::MockRequest.env_for("/?foo=bar")
1204
1363
 
1205
1364
  req1 = MyRequest.new(env)
1206
- req1.GET.should.equal "foo" => "bar"
1207
- req1.params.should.equal :foo => "bar"
1365
+ req1.GET.must_equal "foo" => "bar"
1366
+ req1.params.must_equal :foo => "bar"
1208
1367
 
1209
- req2 = Rack::Request.new(env)
1210
- req2.GET.should.equal "foo" => "bar"
1211
- req2.params.should.equal "foo" => "bar"
1368
+ req2 = make_request(env)
1369
+ req2.GET.must_equal "foo" => "bar"
1370
+ req2.params.must_equal "foo" => "bar"
1212
1371
  end
1213
1372
 
1214
- should "raise TypeError every time if request parameters are broken" do
1373
+ it "raise TypeError every time if request parameters are broken" do
1215
1374
  broken_query = Rack::MockRequest.env_for("/?foo%5B%5D=0&foo%5Bbar%5D=1")
1216
- req = Rack::Request.new(broken_query)
1217
- lambda{req.GET}.should.raise(TypeError)
1218
- lambda{req.params}.should.raise(TypeError)
1375
+ req = make_request(broken_query)
1376
+ lambda{req.GET}.must_raise TypeError
1377
+ lambda{req.params}.must_raise TypeError
1219
1378
  end
1220
1379
 
1221
1380
  (0x20...0x7E).collect { |a|
1222
1381
  b = a.chr
1223
1382
  c = CGI.escape(b)
1224
- should "not strip '#{a}' => '#{c}' => '#{b}' escaped character from parameters when accessed as string" do
1383
+ it "not strip '#{a}' => '#{c}' => '#{b}' escaped character from parameters when accessed as string" do
1225
1384
  url = "/?foo=#{c}bar#{c}"
1226
1385
  env = Rack::MockRequest.env_for(url)
1227
- req2 = Rack::Request.new(env)
1228
- req2.GET.should.equal "foo" => "#{b}bar#{b}"
1229
- req2.params.should.equal "foo" => "#{b}bar#{b}"
1386
+ req2 = make_request(env)
1387
+ req2.GET.must_equal "foo" => "#{b}bar#{b}"
1388
+ req2.params.must_equal "foo" => "#{b}bar#{b}"
1230
1389
  end
1231
1390
  }
1391
+
1392
+ class NonDelegate < Rack::Request
1393
+ def delegate?; false; end
1394
+ end
1395
+
1396
+ def make_request(env)
1397
+ NonDelegate.new env
1398
+ end
1399
+
1400
+ class TestProxyRequest < RackRequestTest
1401
+ class DelegateRequest
1402
+ include Rack::Request::Helpers
1403
+ extend Forwardable
1404
+
1405
+ def_delegators :@req, :has_header?, :get_header, :fetch_header,
1406
+ :each_header, :set_header, :add_header, :delete_header
1407
+
1408
+ def_delegators :@req, :[], :[]=, :values_at
1409
+
1410
+ def initialize(req)
1411
+ @req = req
1412
+ end
1413
+
1414
+ def delegate?; true; end
1415
+
1416
+ def env; @req.env.dup; end
1417
+ end
1418
+
1419
+ def make_request(env)
1420
+ DelegateRequest.new super(env)
1421
+ end
1422
+ end
1232
1423
  end