request_test.rb 44.5 KB
Newer Older
1
require 'abstract_unit'
2

3 4 5 6 7 8
class BaseRequestTest < ActiveSupport::TestCase
  def setup
    @env = {
      :ip_spoofing_check => true,
      "rack.input" => "foo"
    }
9 10 11 12 13
    @original_tld_length = ActionDispatch::Http::URL.tld_length
  end

  def teardown
    ActionDispatch::Http::URL.tld_length = @original_tld_length
14
  end
15 16

  def url_for(options = {})
17
    options = { host: 'www.example.com' }.merge!(options)
18 19 20
    ActionDispatch::Http::URL.url_for(options)
  end

21 22 23 24 25
  protected
    def stub_request(env = {})
      ip_spoofing_check = env.key?(:ip_spoofing_check) ? env.delete(:ip_spoofing_check) : true
      @trusted_proxies ||= nil
      ip_app = ActionDispatch::RemoteIp.new(Proc.new { }, ip_spoofing_check, @trusted_proxies)
26 27
      ActionDispatch::Http::URL.tld_length = env.delete(:tld_length) if env.key?(:tld_length)

28 29 30 31 32 33 34 35
      ip_app.call(env)

      env = @env.merge(env)
      ActionDispatch::Request.new(env)
    end
end

class RequestUrlFor < BaseRequestTest
36 37 38 39 40 41
  test "url_for class method" do
    e = assert_raise(ArgumentError) { url_for(:host => nil) }
    assert_match(/Please provide the :host parameter/, e.message)

    assert_equal '/books', url_for(:only_path => true, :path => '/books')

Y
Yves Senn 已提交
42 43 44
    assert_equal 'http://www.example.com/books/?q=code', url_for(trailing_slash: true, path: '/books?q=code')
    assert_equal 'http://www.example.com/books/?spareslashes=////', url_for(trailing_slash: true, path: '/books?spareslashes=////')

45 46
    assert_equal 'http://www.example.com',  url_for
    assert_equal 'http://api.example.com',  url_for(:subdomain => 'api')
47
    assert_equal 'http://example.com',      url_for(:subdomain => false)
48 49 50 51 52 53 54 55 56
    assert_equal 'http://www.ror.com',      url_for(:domain => 'ror.com')
    assert_equal 'http://api.ror.co.uk',    url_for(:host => 'www.ror.co.uk', :subdomain => 'api', :tld_length => 2)
    assert_equal 'http://www.example.com:8080',   url_for(:port => 8080)
    assert_equal 'https://www.example.com',       url_for(:protocol => 'https')
    assert_equal 'http://www.example.com/docs',   url_for(:path => '/docs')
    assert_equal 'http://www.example.com#signup', url_for(:anchor => 'signup')
    assert_equal 'http://www.example.com/',       url_for(:trailing_slash => true)
    assert_equal 'http://dhh:supersecret@www.example.com', url_for(:user => 'dhh', :password => 'supersecret')
    assert_equal 'http://www.example.com?search=books',    url_for(:params => { :search => 'books' })
57 58
    assert_equal 'http://www.example.com?params=',  url_for(:params => '')
    assert_equal 'http://www.example.com?params=1', url_for(:params => 1)
59
  end
60
end
61

62
class RequestIP < BaseRequestTest
63
  test "remote ip" do
64 65
    request = stub_request 'REMOTE_ADDR' => '1.2.3.4'
    assert_equal '1.2.3.4', request.remote_ip
66

67
    request = stub_request 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6'
68
    assert_equal '3.4.5.6', request.remote_ip
69

70
    request = stub_request 'REMOTE_ADDR' => '1.2.3.4',
71
                           'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
72
    assert_equal '3.4.5.6', request.remote_ip
73

74
    request = stub_request 'REMOTE_ADDR' => '127.0.0.1',
75
                           'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
76
    assert_equal '3.4.5.6', request.remote_ip
J
Jeremy Kemper 已提交
77

78
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,unknown'
79
    assert_equal '3.4.5.6', request.remote_ip
80

81 82
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,172.16.0.1'
    assert_equal '3.4.5.6', request.remote_ip
J
Jeremy Kemper 已提交
83

84 85
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,192.168.0.1'
    assert_equal '3.4.5.6', request.remote_ip
86

87 88
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,10.0.0.1'
    assert_equal '3.4.5.6', request.remote_ip
89

90 91
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6, 10.0.0.1, 10.0.0.1'
    assert_equal '3.4.5.6', request.remote_ip
92

93 94
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,127.0.0.1'
    assert_equal '3.4.5.6', request.remote_ip
95

96
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,192.168.0.1'
97
    assert_equal nil, request.remote_ip
98

99
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 172.31.4.4, 10.0.0.1'
100
    assert_equal '3.4.5.6', request.remote_ip
101

102 103
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address'
    assert_equal nil, request.remote_ip
104
  end
105

106
  test "remote ip spoof detection" do
107 108
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '1.1.1.1',
                           'HTTP_CLIENT_IP'       => '2.2.2.2'
C
Carlhuda 已提交
109
    e = assert_raise(ActionDispatch::RemoteIp::IpSpoofAttackError) {
110
      request.remote_ip
J
Jeremy Kemper 已提交
111
    }
112 113 114
    assert_match(/IP spoofing attack/, e.message)
    assert_match(/HTTP_X_FORWARDED_FOR="1.1.1.1"/, e.message)
    assert_match(/HTTP_CLIENT_IP="2.2.2.2"/, e.message)
115
  end
J
Jeremy Kemper 已提交
116

117
  test "remote ip with spoof detection disabled" do
118
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '1.1.1.1',
C
Carlhuda 已提交
119 120
                           'HTTP_CLIENT_IP'       => '2.2.2.2',
                           :ip_spoofing_check => false
121
    assert_equal '1.1.1.1', request.remote_ip
122 123
  end

124 125 126 127 128 129 130 131
  test "remote ip spoof protection ignores private addresses" do
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '172.17.19.51',
                           'HTTP_CLIENT_IP'       => '172.17.19.51',
                           'REMOTE_ADDR'          => '1.1.1.1',
                           'HTTP_X_BLUECOAT_VIA'  => 'de462e07a2db325e'
    assert_equal '1.1.1.1', request.remote_ip
  end

132 133 134 135
  test "remote ip v6" do
    request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
    assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip

136
    request = stub_request 'REMOTE_ADDR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334'
137 138 139 140 141 142 143 144 145 146
    assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip

    request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
                           'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
    assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip

    request = stub_request 'REMOTE_ADDR' => '::1',
                           'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
    assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip

147 148
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,unknown'
    assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
149

150 151
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,::1'
    assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
152

153 154
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329, ::1, ::1'
    assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
155 156 157 158

    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,::1'
    assert_equal nil, request.remote_ip

159
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334, fe80:0000:0000:0000:0202:b3ff:fe1e:8329, ::1, fc00::, fc01::, fdff'
160
    assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
161

162 163 164
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'FE00::, FDFF::'
    assert_equal 'FE00::', request.remote_ip

165 166
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address'
    assert_equal nil, request.remote_ip
167
  end
168

169
  test "remote ip v6 spoof detection" do
170 171 172 173 174 175 176 177
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329',
                           'HTTP_CLIENT_IP'       => '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
    e = assert_raise(ActionDispatch::RemoteIp::IpSpoofAttackError) {
      request.remote_ip
    }
    assert_match(/IP spoofing attack/, e.message)
    assert_match(/HTTP_X_FORWARDED_FOR="fe80:0000:0000:0000:0202:b3ff:fe1e:8329"/, e.message)
    assert_match(/HTTP_CLIENT_IP="2001:0db8:85a3:0000:0000:8a2e:0370:7334"/, e.message)
178
  end
179

180
  test "remote ip v6 spoof detection disabled" do
181 182 183 184 185 186
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329',
                           'HTTP_CLIENT_IP'       => '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
                           :ip_spoofing_check     => false
    assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
  end

187 188
  test "remote ip with user specified trusted proxies String" do
    @trusted_proxies = "67.205.106.73"
189

190 191
    request = stub_request 'REMOTE_ADDR' => '3.4.5.6',
                           'HTTP_X_FORWARDED_FOR' => '67.205.106.73'
192 193 194
    assert_equal '3.4.5.6', request.remote_ip

    request = stub_request 'REMOTE_ADDR' => '172.16.0.1,67.205.106.73',
195
                           'HTTP_X_FORWARDED_FOR' => '67.205.106.73'
196
    assert_equal '67.205.106.73', request.remote_ip
197

198 199
    request = stub_request 'REMOTE_ADDR' => '67.205.106.73,3.4.5.6',
                           'HTTP_X_FORWARDED_FOR' => '67.205.106.73'
200
    assert_equal '3.4.5.6', request.remote_ip
201

202
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '67.205.106.73,unknown'
203
    assert_equal nil, request.remote_ip
204

205
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 10.0.0.1, 67.205.106.73'
206 207 208
    assert_equal '3.4.5.6', request.remote_ip
  end

209 210 211 212 213 214 215 216 217 218 219 220 221
  test "remote ip v6 with user specified trusted proxies String" do
    @trusted_proxies = 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'

    request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
                           'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
    assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip

    request = stub_request 'REMOTE_ADDR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334',
                           'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
    assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip

    request = stub_request 'REMOTE_ADDR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,::1',
                           'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
222
    assert_equal '::1', request.remote_ip
223 224 225 226 227

    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
    assert_equal nil, request.remote_ip

    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334'
228
    assert_equal "2001:0db8:85a3:0000:0000:8a2e:0370:7334", request.remote_ip
229 230
  end

231 232 233 234 235 236 237
  test "remote ip with user specified trusted proxies Regexp" do
    @trusted_proxies = /^67\.205\.106\.73$/i

    request = stub_request 'REMOTE_ADDR' => '67.205.106.73',
                           'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
    assert_equal '3.4.5.6', request.remote_ip

238 239
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '10.0.0.1, 9.9.9.9, 3.4.5.6, 67.205.106.73'
    assert_equal '3.4.5.6', request.remote_ip
240 241 242 243 244 245 246 247 248
  end

  test "remote ip v6 with user specified trusted proxies Regexp" do
    @trusted_proxies = /^fe80:0000:0000:0000:0202:b3ff:fe1e:8329$/i

    request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
                           'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
    assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip

249 250 251 252 253
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334, fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
    assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
  end

  test "remote ip middleware not present still returns an IP" do
254
    request = stub_request('REMOTE_ADDR' => '127.0.0.1')
255
    assert_equal '127.0.0.1', request.remote_ip
256
  end
257
end
258

259
class RequestDomain < BaseRequestTest
260
  test "domains" do
261 262
    request = stub_request 'HTTP_HOST' => "192.168.1.200"
    assert_nil request.domain
263

264 265
    request = stub_request 'HTTP_HOST' => "foo.192.168.1.200"
    assert_nil request.domain
266

267 268
    request = stub_request 'HTTP_HOST' => "192.168.1.200.com"
    assert_equal "200.com", request.domain
269

270 271
    request = stub_request 'HTTP_HOST' => 'www.rubyonrails.org'
    assert_equal "rubyonrails.org", request.domain
272

273
    request = stub_request 'HTTP_HOST' => "www.rubyonrails.co.uk"
274
    assert_equal "rubyonrails.co.uk", request.domain(2)
275

276 277 278
    request = stub_request 'HTTP_HOST' => "www.rubyonrails.co.uk", :tld_length => 2
    assert_equal "rubyonrails.co.uk", request.domain
  end
279

280
  test "subdomains" do
281 282
    request = stub_request 'HTTP_HOST' => "foobar.foobar.com"
    assert_equal %w( foobar ), request.subdomains
J
José Valim 已提交
283
    assert_equal "foobar", request.subdomain
284

285 286
    request = stub_request 'HTTP_HOST' => "192.168.1.200"
    assert_equal [], request.subdomains
J
José Valim 已提交
287
    assert_equal "", request.subdomain
288

289 290
    request = stub_request 'HTTP_HOST' => "foo.192.168.1.200"
    assert_equal [], request.subdomains
J
José Valim 已提交
291
    assert_equal "", request.subdomain
292

293 294
    request = stub_request 'HTTP_HOST' => "192.168.1.200.com"
    assert_equal %w( 192 168 1 ), request.subdomains
J
José Valim 已提交
295
    assert_equal "192.168.1", request.subdomain
296

297 298
    request = stub_request 'HTTP_HOST' => nil
    assert_equal [], request.subdomains
J
José Valim 已提交
299
    assert_equal "", request.subdomain
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315

    request = stub_request 'HTTP_HOST' => "www.rubyonrails.org"
    assert_equal %w( www ), request.subdomains
    assert_equal "www", request.subdomain

    request = stub_request 'HTTP_HOST' => "www.rubyonrails.co.uk"
    assert_equal %w( www ), request.subdomains(2)
    assert_equal "www", request.subdomain(2)

    request = stub_request 'HTTP_HOST' => "dev.www.rubyonrails.co.uk"
    assert_equal %w( dev www ), request.subdomains(2)
    assert_equal "dev.www", request.subdomain(2)

    request = stub_request 'HTTP_HOST' => "dev.www.rubyonrails.co.uk", :tld_length => 2
    assert_equal %w( dev www ), request.subdomains
    assert_equal "dev.www", request.subdomain
316
  end
317
end
318

319
class RequestPort < BaseRequestTest
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
  test "standard_port" do
    request = stub_request
    assert_equal 80, request.standard_port

    request = stub_request 'HTTPS' => 'on'
    assert_equal 443, request.standard_port
  end

  test "standard_port?" do
    request = stub_request
    assert !request.ssl?
    assert request.standard_port?

    request = stub_request 'HTTPS' => 'on'
    assert request.ssl?
    assert request.standard_port?

    request = stub_request 'HTTP_HOST' => 'www.example.org:8080'
    assert !request.ssl?
    assert !request.standard_port?

    request = stub_request 'HTTP_HOST' => 'www.example.org:8443', 'HTTPS' => 'on'
    assert request.ssl?
    assert !request.standard_port?
  end

346
  test "optional port" do
347
    request = stub_request 'HTTP_HOST' => 'www.example.org:80'
348
    assert_equal nil, request.optional_port
349

350
    request = stub_request 'HTTP_HOST' => 'www.example.org:8080'
351
    assert_equal 8080, request.optional_port
352
  end
353

354 355 356 357 358 359 360
  test "port string" do
    request = stub_request 'HTTP_HOST' => 'www.example.org:80'
    assert_equal '', request.port_string

    request = stub_request 'HTTP_HOST' => 'www.example.org:8080'
    assert_equal ':8080', request.port_string
  end
361
end
362

363
class RequestPath < BaseRequestTest
364
  test "full path" do
365
    request = stub_request 'SCRIPT_NAME' => '', 'PATH_INFO' => '/path/of/some/uri', 'QUERY_STRING' => 'mapped=1'
366 367
    assert_equal "/path/of/some/uri?mapped=1", request.fullpath
    assert_equal "/path/of/some/uri",          request.path_info
368

369
    request = stub_request 'SCRIPT_NAME' => '', 'PATH_INFO' => '/path/of/some/uri'
370 371
    assert_equal "/path/of/some/uri", request.fullpath
    assert_equal "/path/of/some/uri", request.path_info
372

373
    request = stub_request 'SCRIPT_NAME' => '', 'PATH_INFO' => '/'
374 375
    assert_equal "/", request.fullpath
    assert_equal "/", request.path_info
376

377
    request = stub_request 'SCRIPT_NAME' => '', 'PATH_INFO' => '/', 'QUERY_STRING' => 'm=b'
378 379
    assert_equal "/?m=b", request.fullpath
    assert_equal "/",     request.path_info
380

381
    request = stub_request 'SCRIPT_NAME' => '/hieraki', 'PATH_INFO' => '/'
382 383
    assert_equal "/hieraki/", request.fullpath
    assert_equal "/",         request.path_info
384

385
    request = stub_request 'SCRIPT_NAME' => '/collaboration/hieraki', 'PATH_INFO' => '/books/edit/2'
386 387
    assert_equal "/collaboration/hieraki/books/edit/2", request.fullpath
    assert_equal "/books/edit/2",                       request.path_info
388

389
    request = stub_request 'SCRIPT_NAME' => '/path', 'PATH_INFO' => '/of/some/uri', 'QUERY_STRING' => 'mapped=1'
390 391
    assert_equal "/path/of/some/uri?mapped=1", request.fullpath
    assert_equal "/of/some/uri",               request.path_info
392
  end
393

394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
  test "original_fullpath returns ORIGINAL_FULLPATH" do
    request = stub_request('ORIGINAL_FULLPATH' => "/foo?bar")

    path = request.original_fullpath
    assert_equal "/foo?bar", path
  end

  test "original_url returns url built using ORIGINAL_FULLPATH" do
    request = stub_request('ORIGINAL_FULLPATH' => "/foo?bar",
                           'HTTP_HOST'         => "example.org",
                           'rack.url_scheme'   => "http")

    url = request.original_url
    assert_equal "http://example.org/foo?bar", url
  end

  test "original_fullpath returns fullpath if ORIGINAL_FULLPATH is not present" do
    request = stub_request('PATH_INFO'    => "/foo",
                           'QUERY_STRING' => "bar")

    path = request.original_fullpath
    assert_equal "/foo?bar", path
  end
end

class RequestHost < BaseRequestTest
420
  test "host with default port" do
421 422
    request = stub_request 'HTTP_HOST' => 'rubyonrails.org:80'
    assert_equal "rubyonrails.org", request.host_with_port
423
  end
424

425
  test "host with non default port" do
426 427
    request = stub_request 'HTTP_HOST' => 'rubyonrails.org:81'
    assert_equal "rubyonrails.org:81", request.host_with_port
428
  end
429

430 431 432 433 434 435 436 437 438 439 440 441
  test "proxy request" do
    request = stub_request 'HTTP_HOST' => 'glu.ttono.us:80'
    assert_equal "glu.ttono.us", request.host_with_port
  end

  test "http host" do
    request = stub_request 'HTTP_HOST' => "rubyonrails.org:8080"
    assert_equal "rubyonrails.org", request.host
    assert_equal "rubyonrails.org:8080", request.host_with_port

    request = stub_request 'HTTP_X_FORWARDED_HOST' => "www.firsthost.org, www.secondhost.org"
    assert_equal "www.secondhost.org", request.host
442 443 444

    request = stub_request 'HTTP_X_FORWARDED_HOST' => "", 'HTTP_HOST' => "rubyonrails.org"
    assert_equal "rubyonrails.org", request.host
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
  end

  test "http host with default port overrides server port" do
    request = stub_request 'HTTP_HOST' => "rubyonrails.org"
    assert_equal "rubyonrails.org", request.host_with_port
  end

  test "host with port if http standard port is specified" do
    request = stub_request 'HTTP_X_FORWARDED_HOST' => "glu.ttono.us:80"
    assert_equal "glu.ttono.us", request.host_with_port
  end

  test "host with port if https standard port is specified" do
    request = stub_request(
      'HTTP_X_FORWARDED_PROTO' => "https",
      'HTTP_X_FORWARDED_HOST' => "glu.ttono.us:443"
    )
    assert_equal "glu.ttono.us", request.host_with_port
  end

  test "host if ipv6 reference" do
    request = stub_request 'HTTP_HOST' => "[2001:1234:5678:9abc:def0::dead:beef]"
    assert_equal "[2001:1234:5678:9abc:def0::dead:beef]", request.host
  end

  test "host if ipv6 reference with port" do
    request = stub_request 'HTTP_HOST' => "[2001:1234:5678:9abc:def0::dead:beef]:8008"
    assert_equal "[2001:1234:5678:9abc:def0::dead:beef]", request.host
  end
end

class RequestCGI < BaseRequestTest
  test "CGI environment variables" do
    request = stub_request(
      "AUTH_TYPE" => "Basic",
      "GATEWAY_INTERFACE" => "CGI/1.1",
      "HTTP_ACCEPT" => "*/*",
      "HTTP_ACCEPT_CHARSET" => "UTF-8",
      "HTTP_ACCEPT_ENCODING" => "gzip, deflate",
      "HTTP_ACCEPT_LANGUAGE" => "en",
      "HTTP_CACHE_CONTROL" => "no-cache, max-age=0",
      "HTTP_FROM" => "googlebot",
      "HTTP_HOST" => "glu.ttono.us:8007",
      "HTTP_NEGOTIATE" => "trans",
      "HTTP_PRAGMA" => "no-cache",
      "HTTP_REFERER" => "http://www.google.com/search?q=glu.ttono.us",
      "HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en)",
      "PATH_INFO" => "/homepage/",
      "PATH_TRANSLATED" => "/home/kevinc/sites/typo/public/homepage/",
      "QUERY_STRING" => "",
      "REMOTE_ADDR" => "207.7.108.53",
      "REMOTE_HOST" => "google.com",
      "REMOTE_IDENT" => "kevin",
      "REMOTE_USER" => "kevin",
      "REQUEST_METHOD" => "GET",
      "SCRIPT_NAME" => "/dispatch.fcgi",
      "SERVER_NAME" => "glu.ttono.us",
      "SERVER_PORT" => "8007",
      "SERVER_PROTOCOL" => "HTTP/1.1",
      "SERVER_SOFTWARE" => "lighttpd/1.4.5",
    )

    assert_equal "Basic", request.auth_type
    assert_equal 0, request.content_length
    assert_equal nil, request.content_mime_type
    assert_equal "CGI/1.1", request.gateway_interface
    assert_equal "*/*", request.accept
    assert_equal "UTF-8", request.accept_charset
    assert_equal "gzip, deflate", request.accept_encoding
    assert_equal "en", request.accept_language
    assert_equal "no-cache, max-age=0", request.cache_control
    assert_equal "googlebot", request.from
    assert_equal "glu.ttono.us", request.host
    assert_equal "trans", request.negotiate
    assert_equal "no-cache", request.pragma
    assert_equal "http://www.google.com/search?q=glu.ttono.us", request.referer
    assert_equal "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en)", request.user_agent
    assert_equal "/homepage/", request.path_info
    assert_equal "/home/kevinc/sites/typo/public/homepage/", request.path_translated
    assert_equal "", request.query_string
    assert_equal "207.7.108.53", request.remote_addr
    assert_equal "google.com", request.remote_host
    assert_equal "kevin", request.remote_ident
    assert_equal "kevin", request.remote_user
    assert_equal "GET", request.request_method
    assert_equal "/dispatch.fcgi", request.script_name
    assert_equal "glu.ttono.us", request.server_name
    assert_equal 8007, request.server_port
    assert_equal "HTTP/1.1", request.server_protocol
    assert_equal "lighttpd", request.server_software
  end
end

538 539 540
class LocalhostTest < BaseRequestTest
  test "IPs that match localhost" do
    request = stub_request("REMOTE_IP" => "127.1.1.1", "REMOTE_ADDR" => "127.1.1.1")
A
Arthur Neves 已提交
541
    assert request.local?
542 543 544
  end
end

545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
class RequestCookie < BaseRequestTest
  test "cookie syntax resilience" do
    request = stub_request("HTTP_COOKIE" => "_session_id=c84ace84796670c052c6ceb2451fb0f2; is_admin=yes")
    assert_equal "c84ace84796670c052c6ceb2451fb0f2", request.cookies["_session_id"], request.cookies.inspect
    assert_equal "yes", request.cookies["is_admin"], request.cookies.inspect

    # some Nokia phone browsers omit the space after the semicolon separator.
    # some developers have grown accustomed to using comma in cookie values.
    request = stub_request("HTTP_COOKIE"=>"_session_id=c84ace847,96670c052c6ceb2451fb0f2;is_admin=yes")
    assert_equal "c84ace847", request.cookies["_session_id"], request.cookies.inspect
    assert_equal "yes", request.cookies["is_admin"], request.cookies.inspect
  end
end

class RequestParamsParsing < BaseRequestTest
  test "doesnt break when content type has charset" do
    request = stub_request(
      'REQUEST_METHOD' => 'POST',
      'CONTENT_LENGTH' => "flamenco=love".length,
      'CONTENT_TYPE' => 'application/x-www-form-urlencoded; charset=utf-8',
      'rack.input' => StringIO.new("flamenco=love")
    )

    assert_equal({"flamenco"=> "love"}, request.request_parameters)
  end

  test "doesnt interpret request uri as query string when missing" do
    request = stub_request('REQUEST_URI' => 'foo')
    assert_equal({}, request.query_parameters)
  end
end
576

577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
class RequestRewind < BaseRequestTest
  test "body should be rewound" do
    data = 'rewind'
    env = {
      'rack.input' => StringIO.new(data),
      'CONTENT_LENGTH' => data.length,
      'CONTENT_TYPE' => 'application/x-www-form-urlencoded; charset=utf-8'
    }

    # Read the request body by parsing params.
    request = stub_request(env)
    request.request_parameters

    # Should have rewound the body.
    assert_equal 0, request.body.pos
  end

  test "raw_post rewinds rack.input if RAW_POST_DATA is nil" do
    request = stub_request(
      'rack.input' => StringIO.new("raw"),
      'CONTENT_LENGTH' => 3
    )
    assert_equal "raw", request.raw_post
    assert_equal "raw", request.env['rack.input'].read
  end
end
603

604 605 606 607
class RequestProtocol < BaseRequestTest
  test "server software" do
    assert_equal 'lighttpd', stub_request('SERVER_SOFTWARE' => 'lighttpd/1.4.5').server_software
    assert_equal 'apache', stub_request('SERVER_SOFTWARE' => 'Apache3.422').server_software
608
  end
609

610
  test "xml http request" do
611 612 613 614
    request = stub_request

    assert !request.xml_http_request?
    assert !request.xhr?
615

616 617 618
    request = stub_request 'HTTP_X_REQUESTED_WITH' => 'DefinitelyNotAjax1.0'
    assert !request.xml_http_request?
    assert !request.xhr?
619

620 621 622
    request = stub_request 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest'
    assert request.xml_http_request?
    assert request.xhr?
623
  end
624

625
  test "reports ssl" do
626 627
    assert !stub_request.ssl?
    assert stub_request('HTTPS' => 'on').ssl?
628 629
  end

630
  test "reports ssl when proxied via lighttpd" do
631
    assert stub_request('HTTP_X_FORWARDED_PROTO' => 'https').ssl?
632
  end
633

634 635 636 637 638
  test "scheme returns https when proxied" do
    request = stub_request 'rack.url_scheme' => 'http'
    assert !request.ssl?
    assert_equal 'http', request.scheme

639 640 641 642
    request = stub_request(
      'rack.url_scheme' => 'http',
      'HTTP_X_FORWARDED_PROTO' => 'https'
    )
643 644 645
    assert request.ssl?
    assert_equal 'https', request.scheme
  end
646
end
647

648
class RequestMethod < BaseRequestTest
649
  test "method returns environment's request method when it has not been
650
    overridden by middleware".squish do
651

652 653 654 655 656
    ActionDispatch::Request::HTTP_METHODS.each do |method|
      request = stub_request('REQUEST_METHOD' => method)

      assert_equal method, request.method
      assert_equal method.underscore.to_sym, request.method_symbol
657 658 659
    end
  end

660 661 662 663 664 665 666 667 668 669
  test "allow request method hacking" do
    request = stub_request('REQUEST_METHOD' => 'POST')

    assert_equal 'POST', request.request_method
    assert_equal 'POST', request.env["REQUEST_METHOD"]

    request.request_method = 'GET'

    assert_equal 'GET', request.request_method
    assert_equal 'GET', request.env["REQUEST_METHOD"]
670
    assert request.get?
671 672
  end

673
  test "invalid http method raises exception" do
674
    assert_raise(ActionController::UnknownHttpMethod) do
675
      stub_request('REQUEST_METHOD' => 'RANDOM_METHOD').request_method
676 677 678
    end
  end

G
Guo Xiang Tan 已提交
679 680 681
  test "method returns original value of environment request method on POST" do
    request = stub_request('rack.methodoverride.original_method' => 'POST')
    assert_equal 'POST', request.method
682 683
  end

G
Guo Xiang Tan 已提交
684
  test "method raises exception on invalid HTTP method" do
685
    assert_raise(ActionController::UnknownHttpMethod) do
G
Guo Xiang Tan 已提交
686
      stub_request('rack.methodoverride.original_method' => '_RANDOM_METHOD').method
687
    end
688

G
Guo Xiang Tan 已提交
689 690
    assert_raise(ActionController::UnknownHttpMethod) do
      stub_request('REQUEST_METHOD' => '_RANDOM_METHOD').method
691 692
    end
  end
693

694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
  test "exception on invalid HTTP method unaffected by I18n settings" do
    old_locales = I18n.available_locales
    old_enforce = I18n.config.enforce_available_locales

    begin
      I18n.available_locales = [:nl]
      I18n.config.enforce_available_locales = true
      assert_raise(ActionController::UnknownHttpMethod) do
        stub_request('REQUEST_METHOD' => '_RANDOM_METHOD').method
      end
    ensure
      I18n.available_locales = old_locales
      I18n.config.enforce_available_locales = old_enforce
    end
  end

710
  test "post masquerading as patch" do
711 712 713 714 715
    request = stub_request(
      'REQUEST_METHOD' => 'PATCH',
      "rack.methodoverride.original_method" => "POST"
    )

716 717 718 719 720
    assert_equal "POST", request.method
    assert_equal "PATCH",  request.request_method
    assert request.patch?
  end

721
  test "post masquerading as put" do
722 723 724 725
    request = stub_request(
      'REQUEST_METHOD' => 'PUT',
      "rack.methodoverride.original_method" => "POST"
    )
726 727 728 729 730
    assert_equal "POST", request.method
    assert_equal "PUT",  request.request_method
    assert request.put?
  end

731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
  test "post uneffected by local inflections" do
    existing_acrnoyms = ActiveSupport::Inflector.inflections.acronyms.dup
    existing_acrnoym_regex = ActiveSupport::Inflector.inflections.acronym_regex.dup
    begin
      ActiveSupport::Inflector.inflections do |inflect|
        inflect.acronym "POS"
      end
      assert_equal "pos_t", "POST".underscore
      request = stub_request "REQUEST_METHOD" => "POST"
      assert_equal :post, ActionDispatch::Request::HTTP_METHOD_LOOKUP["POST"]
      assert_equal :post, request.method_symbol
      assert request.post?
    ensure
      # Reset original acronym set
      ActiveSupport::Inflector.inflections do |inflect|
        inflect.send(:instance_variable_set,"@acronyms",existing_acrnoyms)
        inflect.send(:instance_variable_set,"@acronym_regex",existing_acrnoym_regex)
      end
    end
  end
751
end
752

753
class RequestFormat < BaseRequestTest
754
  test "xml format" do
755
    request = stub_request
756
    assert_called(request, :parameters, times: 2, returns: {format: :xml}) do
757
      assert_equal Mime[:xml], request.format
758
    end
759
  end
760

761
  test "xhtml format" do
762
    request = stub_request
763
    assert_called(request, :parameters, times: 2, returns: {format: :xhtml}) do
764
      assert_equal Mime[:html], request.format
765
    end
766
  end
767

768
  test "txt format" do
769
    request = stub_request
770
    assert_called(request, :parameters, times: 2, returns: {format: :txt}) do
771
      assert_equal Mime[:text], request.format
772
    end
773
  end
774

775
  test "XMLHttpRequest" do
776 777
    request = stub_request(
      'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest',
778
      'HTTP_ACCEPT' => [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(",")
779
    )
780 781 782

    assert_called(request, :parameters, times: 1, returns: {}) do
      assert request.xhr?
783
      assert_equal Mime[:js], request.format
784
    end
785
  end
786

787
  test "can override format with parameter negative" do
788
    request = stub_request
789 790 791
    assert_called(request, :parameters, times: 2, returns: {format: :txt}) do
      assert !request.format.xml?
    end
792
  end
793

794
  test "can override format with parameter positive" do
795
    request = stub_request
796 797 798
    assert_called(request, :parameters, times: 2, returns: {format: :xml}) do
      assert request.format.xml?
    end
799 800
  end

801
  test "formats text/html with accept header" do
802
    request = stub_request 'HTTP_ACCEPT' => 'text/html'
803
    assert_equal [Mime[:html]], request.formats
804
  end
805

806
  test "formats blank with accept header" do
807
    request = stub_request 'HTTP_ACCEPT' => ''
808
    assert_equal [Mime[:html]], request.formats
809
  end
810

811 812
  test "formats XMLHttpRequest with accept header" do
    request = stub_request 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
813
    assert_equal [Mime[:js]], request.formats
814
  end
815

816 817 818
  test "formats application/xml with accept header" do
    request = stub_request('CONTENT_TYPE' => 'application/xml; charset=UTF-8',
                           'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest")
819
    assert_equal [Mime[:xml]], request.formats
820
  end
821

822
  test "formats format:text with accept header" do
823
    request = stub_request
824
    assert_called(request, :parameters, times: 2, returns: {format: :txt}) do
825
      assert_equal [Mime[:text]], request.formats
826
    end
827
  end
828

829
  test "formats format:unknown with accept header" do
830
    request = stub_request
831 832 833
    assert_called(request, :parameters, times: 2, returns: {format: :unknown}) do
      assert_instance_of Mime::NullType, request.format
    end
834 835
  end

836 837
  test "format is not nil with unknown format" do
    request = stub_request
838 839 840 841 842 843
    assert_called(request, :parameters, times: 2, returns: {format: :hello}) do
      assert request.format.nil?
      assert_not request.format.html?
      assert_not request.format.xml?
      assert_not request.format.json?
    end
844
  end
845

J
Jarmo Isotalo 已提交
846 847 848 849 850 851
  test "format does not throw exceptions when malformed parameters" do
    request = stub_request("QUERY_STRING" => "x[y]=1&x[y][][w]=2")
    assert request.formats
    assert request.format.html?
  end

852 853
  test "formats with xhr request" do
    request = stub_request 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
854
    assert_called(request, :parameters, times: 1, returns: {}) do
855
      assert_equal [Mime[:js]], request.formats
856
    end
857 858
  end

859
  test "ignore_accept_header" do
860
    old_ignore_accept_header = ActionDispatch::Request.ignore_accept_header
861 862 863 864
    ActionDispatch::Request.ignore_accept_header = true

    begin
      request = stub_request 'HTTP_ACCEPT' => 'application/xml'
865
      assert_called(request, :parameters, times: 1, returns: {}) do
866
        assert_equal [ Mime[:html] ], request.formats
867
      end
868

J
José Valim 已提交
869
      request = stub_request 'HTTP_ACCEPT' => 'koz-asked/something-crazy'
870
      assert_called(request, :parameters, times: 1, returns: {}) do
871
        assert_equal [ Mime[:html] ], request.formats
872
      end
J
José Valim 已提交
873 874

      request = stub_request 'HTTP_ACCEPT' => '*/*;q=0.1'
875
      assert_called(request, :parameters, times: 1, returns: {}) do
876
        assert_equal [ Mime[:html] ], request.formats
877
      end
J
José Valim 已提交
878 879

      request = stub_request 'HTTP_ACCEPT' => 'application/jxw'
880
      assert_called(request, :parameters, times: 1, returns: {}) do
881
        assert_equal [ Mime[:html] ], request.formats
882
      end
J
José Valim 已提交
883

884 885
      request = stub_request 'HTTP_ACCEPT' => 'application/xml',
                             'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
886 887

      assert_called(request, :parameters, times: 1, returns: {}) do
888
        assert_equal [ Mime[:js] ], request.formats
889
      end
890 891 892

      request = stub_request 'HTTP_ACCEPT' => 'application/xml',
                             'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
893
      assert_called(request, :parameters, times: 2, returns: {format: :json}) do
894
        assert_equal [ Mime[:json] ], request.formats
895
      end
896
    ensure
897
      ActionDispatch::Request.ignore_accept_header = old_ignore_accept_header
898 899
    end
  end
900
end
901

902 903
class RequestMimeType < BaseRequestTest
  test "content type" do
904
    assert_equal Mime[:html], stub_request('CONTENT_TYPE' => 'text/html').content_mime_type
905
  end
906

907 908 909 910 911
  test "no content type" do
    assert_equal nil, stub_request.content_mime_type
  end

  test "content type is XML" do
912
    assert_equal Mime[:xml], stub_request('CONTENT_TYPE' => 'application/xml').content_mime_type
913 914 915
  end

  test "content type with charset" do
916
    assert_equal Mime[:xml], stub_request('CONTENT_TYPE' => 'application/xml; charset=UTF-8').content_mime_type
917 918 919 920 921 922 923 924 925 926 927
  end

  test "user agent" do
    assert_equal 'TestAgent', stub_request('HTTP_USER_AGENT' => 'TestAgent').user_agent
  end

  test "negotiate_mime" do
    request = stub_request(
      'HTTP_ACCEPT' => 'text/html',
      'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
    )
928

929 930 931
    assert_equal nil, request.negotiate_mime([Mime[:xml], Mime[:json]])
    assert_equal Mime[:html], request.negotiate_mime([Mime[:xml], Mime[:html]])
    assert_equal Mime[:html], request.negotiate_mime([Mime[:xml], Mime::ALL])
932 933 934 935 936 937 938
  end

  test "negotiate_mime with content_type" do
    request = stub_request(
      'CONTENT_TYPE' => 'application/xml; charset=UTF-8',
      'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
    )
939

940
    assert_equal Mime[:xml], request.negotiate_mime([Mime[:xml], Mime[:csv]])
941
  end
942
end
943

944 945 946 947
class RequestParameters < BaseRequestTest
  test "parameters" do
    request = stub_request

948 949 950 951 952 953 954
    assert_called(request, :request_parameters, times: 2, returns: {"foo" => 1}) do
      assert_called(request, :query_parameters, times: 2, returns: {"bar" => 2}) do
        assert_equal({"foo" => 1, "bar" => 2}, request.parameters)
        assert_equal({"foo" => 1}, request.request_parameters)
        assert_equal({"bar" => 2}, request.query_parameters)
      end
    end
955 956
  end

J
Jarmo Isotalo 已提交
957
  test "parameters not accessible after rack parse error" do
958 959
    request = stub_request("QUERY_STRING" => "x[y]=1&x[y][][w]=2")

J
Jarmo Isotalo 已提交
960 961
    2.times do
      assert_raises(ActionController::BadRequest) do
962
        # rack will raise a Rack::Utils::ParameterTypeError when parsing this query string
J
Jarmo Isotalo 已提交
963 964
        request.parameters
      end
965
    end
966 967
  end

968 969 970 971 972 973 974 975 976 977 978 979 980 981
  test "path parameters with invalid UTF8 encoding" do
    request = stub_request(
      "action_dispatch.request.path_parameters" => { foo: "\xBE" }
    )

    err = assert_raises(ActionController::BadRequest) do
      request.check_path_parameters!
    end

    assert_match "Invalid parameter encoding", err.message
    assert_match "foo", err.message
    assert_match "\\xBE", err.message
  end

982 983
  test "parameters not accessible after rack parse error of invalid UTF8 character" do
    request = stub_request("QUERY_STRING" => "foo%81E=1")
984 985
    assert_raises(ActionController::BadRequest) { request.parameters }
  end
986

987 988 989 990 991 992 993 994
  test "parameters containing an invalid UTF8 character" do
    request = stub_request("QUERY_STRING" => "foo=%81E")
    assert_raises(ActionController::BadRequest) { request.parameters }
  end

  test "parameters containing a deeply nested invalid UTF8 character" do
    request = stub_request("QUERY_STRING" => "foo[bar]=%81E")
    assert_raises(ActionController::BadRequest) { request.parameters }
995 996 997 998 999 1000 1001 1002 1003 1004 1005
  end

  test "parameters not accessible after rack parse error 1" do
    request = stub_request(
      'REQUEST_METHOD' => 'POST',
      'CONTENT_LENGTH' => "a%=".length,
      'CONTENT_TYPE' => 'application/x-www-form-urlencoded; charset=utf-8',
      'rack.input' => StringIO.new("a%=")
    )

    assert_raises(ActionController::BadRequest) do
1006
      # rack will raise a Rack::Utils::ParameterTypeError when parsing this query string
1007 1008 1009 1010
      request.parameters
    end
  end

1011 1012 1013 1014
  test "we have access to the original exception" do
    request = stub_request("QUERY_STRING" => "x[y]=1&x[y][][w]=2")

    e = assert_raises(ActionController::BadRequest) do
1015
      # rack will raise a Rack::Utils::ParameterTypeError when parsing this query string
1016 1017 1018
      request.parameters
    end

1019 1020
    assert_not_nil e.cause
    assert_equal e.cause.backtrace, e.backtrace
1021 1022 1023 1024 1025
  end
end


class RequestParameterFilter < BaseRequestTest
1026
  test "process parameter filter" do
1027 1028 1029 1030 1031 1032 1033
    test_hashes = [
    [{'foo'=>'bar'},{'foo'=>'bar'},%w'food'],
    [{'foo'=>'bar'},{'foo'=>'[FILTERED]'},%w'foo'],
    [{'foo'=>'bar', 'bar'=>'foo'},{'foo'=>'[FILTERED]', 'bar'=>'foo'},%w'foo baz'],
    [{'foo'=>'bar', 'baz'=>'foo'},{'foo'=>'[FILTERED]', 'baz'=>'[FILTERED]'},%w'foo baz'],
    [{'bar'=>{'foo'=>'bar','bar'=>'foo'}},{'bar'=>{'foo'=>'[FILTERED]','bar'=>'foo'}},%w'fo'],
    [{'foo'=>{'foo'=>'bar','bar'=>'foo'}},{'foo'=>'[FILTERED]'},%w'f banana'],
1034
    [{'deep'=>{'cc'=>{'code'=>'bar','bar'=>'foo'},'ss'=>{'code'=>'bar'}}},{'deep'=>{'cc'=>{'code'=>'[FILTERED]','bar'=>'foo'},'ss'=>{'code'=>'bar'}}},%w'deep.cc.code'],
1035
    [{'baz'=>[{'foo'=>'baz'}, "1"]}, {'baz'=>[{'foo'=>'[FILTERED]'}, "1"]}, [/foo/]]]
1036 1037

    test_hashes.each do |before_filter, after_filter, filter_words|
1038 1039
      parameter_filter = ActionDispatch::Http::ParameterFilter.new(filter_words)
      assert_equal after_filter, parameter_filter.filter(before_filter)
1040

1041 1042
      filter_words << 'blah'
      filter_words << lambda { |key, value|
1043
        value.reverse! if key =~ /bargain/
1044
      }
1045

1046
      parameter_filter = ActionDispatch::Http::ParameterFilter.new(filter_words)
1047 1048
      before_filter['barg'] = {:bargain=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}}
      after_filter['barg']  = {:bargain=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}}
1049

1050
      assert_equal after_filter, parameter_filter.filter(before_filter)
1051 1052
    end
  end
1053

1054
  test "filtered_parameters returns params filtered" do
1055 1056 1057 1058 1059 1060 1061 1062
    request = stub_request(
      'action_dispatch.request.parameters' => {
        'lifo' => 'Pratik',
        'amount' => '420',
        'step' => '1'
      },
      'action_dispatch.parameter_filter' => [:lifo, :amount]
    )
1063 1064 1065 1066 1067 1068 1069 1070

    params = request.filtered_parameters
    assert_equal "[FILTERED]", params["lifo"]
    assert_equal "[FILTERED]", params["amount"]
    assert_equal "1", params["step"]
  end

  test "filtered_env filters env as a whole" do
1071 1072 1073 1074 1075 1076 1077 1078
    request = stub_request(
      'action_dispatch.request.parameters' => {
        'amount' => '420',
        'step' => '1'
      },
      "RAW_POST_DATA" => "yada yada",
      'action_dispatch.parameter_filter' => [:lifo, :amount]
    )
1079
    request = stub_request(request.filtered_env)
1080 1081 1082

    assert_equal "[FILTERED]", request.raw_post
    assert_equal "[FILTERED]", request.params["amount"]
1083
    assert_equal "1", request.params["step"]
1084 1085
  end

1086 1087
  test "filtered_path returns path with filtered query string" do
    %w(; &).each do |sep|
1088 1089
      request = stub_request(
        'QUERY_STRING' => %w(username=sikachu secret=bd4f21f api_key=b1bc3b3cd352f68d79d7).join(sep),
1090
        'PATH_INFO' => '/authenticate',
1091 1092
        'action_dispatch.parameter_filter' => [:secret, :api_key]
      )
1093 1094 1095 1096 1097 1098 1099

      path = request.filtered_path
      assert_equal %w(/authenticate?username=sikachu secret=[FILTERED] api_key=[FILTERED]).join(sep), path
    end
  end

  test "filtered_path should not unescape a genuine '[FILTERED]' value" do
1100 1101
    request = stub_request(
      'QUERY_STRING' => "secret=bd4f21f&genuine=%5BFILTERED%5D",
1102
      'PATH_INFO' => '/authenticate',
1103 1104
      'action_dispatch.parameter_filter' => [:secret]
    )
1105 1106

    path = request.filtered_path
1107
    assert_equal request.script_name + "/authenticate?secret=[FILTERED]&genuine=%5BFILTERED%5D", path
1108 1109 1110
  end

  test "filtered_path should preserve duplication of keys in query string" do
1111 1112
    request = stub_request(
      'QUERY_STRING' => "username=sikachu&secret=bd4f21f&username=fxn",
1113
      'PATH_INFO' => '/authenticate',
1114 1115
      'action_dispatch.parameter_filter' => [:secret]
    )
1116 1117

    path = request.filtered_path
1118
    assert_equal request.script_name + "/authenticate?username=sikachu&secret=[FILTERED]&username=fxn", path
1119 1120 1121
  end

  test "filtered_path should ignore searchparts" do
1122 1123
    request = stub_request(
      'QUERY_STRING' => "secret",
1124
      'PATH_INFO' => '/authenticate',
1125 1126
      'action_dispatch.parameter_filter' => [:secret]
    )
1127 1128

    path = request.filtered_path
1129
    assert_equal request.script_name + "/authenticate?secret", path
1130
  end
1131
end
1132

1133
class RequestEtag < BaseRequestTest
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
  test "if_none_match_etags none" do
    request = stub_request

    assert_equal nil, request.if_none_match
    assert_equal [], request.if_none_match_etags
    assert !request.etag_matches?("foo")
    assert !request.etag_matches?(nil)
  end

  test "if_none_match_etags single" do
    header = 'the-etag'
    request = stub_request('HTTP_IF_NONE_MATCH' => header)

    assert_equal header, request.if_none_match
    assert_equal [header], request.if_none_match_etags
    assert request.etag_matches?("the-etag")
  end

  test "if_none_match_etags quoted single" do
    header = '"the-etag"'
    request = stub_request('HTTP_IF_NONE_MATCH' => header)

    assert_equal header, request.if_none_match
    assert_equal ['the-etag'], request.if_none_match_etags
    assert request.etag_matches?("the-etag")
  end

  test "if_none_match_etags multiple" do
    header = 'etag1, etag2, "third etag", "etag4"'
    expected = ['etag1', 'etag2', 'third etag', 'etag4']
    request = stub_request('HTTP_IF_NONE_MATCH' => header)

    assert_equal header, request.if_none_match
    assert_equal expected, request.if_none_match_etags
    expected.each do |etag|
      assert request.etag_matches?(etag), etag
    end
  end
1172
end
1173

R
Rafael Mendonça França 已提交
1174
class RequestVariant < BaseRequestTest
1175 1176
  def setup
    super
1177 1178
    @request = stub_request
  end
L
Lukasz Strzalkowski 已提交
1179

1180 1181
  test 'setting variant to a symbol' do
    @request.variant = :phone
L
Lukasz Strzalkowski 已提交
1182

1183 1184 1185 1186 1187
    assert @request.variant.phone?
    assert_not @request.variant.tablet?
    assert @request.variant.any?(:phone, :tablet)
    assert_not @request.variant.any?(:tablet, :desktop)
  end
1188

1189 1190
  test 'setting variant to an array of symbols' do
    @request.variant = [:phone, :tablet]
1191

1192 1193 1194 1195 1196
    assert @request.variant.phone?
    assert @request.variant.tablet?
    assert_not @request.variant.desktop?
    assert @request.variant.any?(:tablet, :desktop)
    assert_not @request.variant.any?(:desktop, :watch)
Ł
Łukasz Strzałkowski 已提交
1197 1198
  end

1199 1200
  test 'clearing variant' do
    @request.variant = nil
1201

1202 1203 1204
    assert @request.variant.empty?
    assert_not @request.variant.phone?
    assert_not @request.variant.any?(:phone, :tablet)
1205 1206
  end

1207 1208 1209 1210 1211 1212 1213
  test 'setting variant to a non-symbol value' do
    assert_raise ArgumentError do
      @request.variant = 'phone'
    end
  end

  test 'setting variant to an array containing a non-symbol value' do
Ł
Łukasz Strzałkowski 已提交
1214
    assert_raise ArgumentError do
1215
      @request.variant = [:phone, 'tablet']
Ł
Łukasz Strzałkowski 已提交
1216 1217
    end
  end
1218
end
S
Sergey Alekseev 已提交
1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238

class RequestFormData < BaseRequestTest
  test 'media_type is from the FORM_DATA_MEDIA_TYPES array' do
    assert stub_request('CONTENT_TYPE' => 'application/x-www-form-urlencoded').form_data?
    assert stub_request('CONTENT_TYPE' => 'multipart/form-data').form_data?
  end

  test 'media_type is not from the FORM_DATA_MEDIA_TYPES array' do
    assert !stub_request('CONTENT_TYPE' => 'application/xml').form_data?
    assert !stub_request('CONTENT_TYPE' => 'multipart/related').form_data?
  end

  test 'no Content-Type header is provided and the request_method is POST' do
    request = stub_request('REQUEST_METHOD' => 'POST')

    assert_equal '', request.media_type
    assert_equal 'POST', request.request_method
    assert !request.form_data?
  end
end