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

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

  def url_for(options = {})
13
    options = { host: 'www.example.com' }.merge!(options)
14 15 16
    ActionDispatch::Http::URL.url_for(options)
  end

17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
  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)
      tld_length = env.key?(:tld_length) ? env.delete(:tld_length) : 1
      ip_app.call(env)
      ActionDispatch::Http::URL.tld_length = tld_length

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

class RequestUrlFor < BaseRequestTest
32 33 34 35 36 37
  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 已提交
38 39 40
    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=////')

41 42
    assert_equal 'http://www.example.com',  url_for
    assert_equal 'http://api.example.com',  url_for(:subdomain => 'api')
43
    assert_equal 'http://example.com',      url_for(:subdomain => false)
44 45 46 47 48 49 50 51 52
    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' })
53 54
    assert_equal 'http://www.example.com?params=',  url_for(:params => '')
    assert_equal 'http://www.example.com?params=1', url_for(:params => 1)
55
  end
56
end
57

58
class RequestIP < BaseRequestTest
59
  test "remote ip" do
60 61
    request = stub_request 'REMOTE_ADDR' => '1.2.3.4'
    assert_equal '1.2.3.4', request.remote_ip
62

63
    request = stub_request 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6'
64
    assert_equal '3.4.5.6', request.remote_ip
65

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

70
    request = stub_request 'REMOTE_ADDR' => '127.0.0.1',
71
                           'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
72
    assert_equal '3.4.5.6', request.remote_ip
J
Jeremy Kemper 已提交
73

74
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,unknown'
75
    assert_equal '3.4.5.6', request.remote_ip
76

77 78
    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 已提交
79

80 81
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,192.168.0.1'
    assert_equal '3.4.5.6', request.remote_ip
82

83 84
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,10.0.0.1'
    assert_equal '3.4.5.6', request.remote_ip
85

86 87
    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
88

89 90
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,127.0.0.1'
    assert_equal '3.4.5.6', request.remote_ip
91

92
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,192.168.0.1'
93
    assert_equal nil, request.remote_ip
94

95
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 172.31.4.4, 10.0.0.1'
96
    assert_equal '3.4.5.6', request.remote_ip
97

98 99
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address'
    assert_equal nil, request.remote_ip
100
  end
101

102
  test "remote ip spoof detection" do
103 104
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '1.1.1.1',
                           'HTTP_CLIENT_IP'       => '2.2.2.2'
C
Carlhuda 已提交
105
    e = assert_raise(ActionDispatch::RemoteIp::IpSpoofAttackError) {
106
      request.remote_ip
J
Jeremy Kemper 已提交
107
    }
108 109 110
    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)
111
  end
J
Jeremy Kemper 已提交
112

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

120 121 122 123 124 125 126 127
  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

128 129 130 131
  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

132
    request = stub_request 'REMOTE_ADDR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334'
133 134 135 136 137 138 139 140 141 142
    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

143 144
    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
145

146 147
    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
148

149 150
    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
151 152 153 154

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

155
    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'
156
    assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
157

158 159 160
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'FE00::, FDFF::'
    assert_equal 'FE00::', request.remote_ip

161 162
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address'
    assert_equal nil, request.remote_ip
163
  end
164

165
  test "remote ip v6 spoof detection" do
166 167 168 169 170 171 172 173
    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)
174
  end
175

176
  test "remote ip v6 spoof detection disabled" do
177 178 179 180 181 182
    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

183 184
  test "remote ip with user specified trusted proxies String" do
    @trusted_proxies = "67.205.106.73"
185

186 187
    request = stub_request 'REMOTE_ADDR' => '3.4.5.6',
                           'HTTP_X_FORWARDED_FOR' => '67.205.106.73'
188 189 190
    assert_equal '3.4.5.6', request.remote_ip

    request = stub_request 'REMOTE_ADDR' => '172.16.0.1,67.205.106.73',
191
                           'HTTP_X_FORWARDED_FOR' => '67.205.106.73'
192
    assert_equal '67.205.106.73', request.remote_ip
193

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

198
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '67.205.106.73,unknown'
199
    assert_equal nil, request.remote_ip
200

201
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 10.0.0.1, 67.205.106.73'
202 203 204
    assert_equal '3.4.5.6', request.remote_ip
  end

205 206 207 208 209 210 211 212 213 214 215 216 217
  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'
218
    assert_equal '::1', request.remote_ip
219 220 221 222 223

    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'
224
    assert_equal "2001:0db8:85a3:0000:0000:8a2e:0370:7334", request.remote_ip
225 226
  end

227 228 229 230 231 232 233
  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

234 235
    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
236 237 238 239 240 241 242 243 244
  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

245 246 247 248 249
    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
250
    request = stub_request('REMOTE_ADDR' => '127.0.0.1')
251
    assert_equal '127.0.0.1', request.remote_ip
252
  end
253
end
254

255
class RequestDomain < BaseRequestTest
256
  test "domains" do
257 258
    request = stub_request 'HTTP_HOST' => 'www.rubyonrails.org'
    assert_equal "rubyonrails.org", request.domain
259

260 261
    request = stub_request 'HTTP_HOST' => "www.rubyonrails.co.uk"
    assert_equal "rubyonrails.co.uk", request.domain(2)
262

263 264 265
    request = stub_request 'HTTP_HOST' => "www.rubyonrails.co.uk", :tld_length => 2
    assert_equal "rubyonrails.co.uk", request.domain

266 267
    request = stub_request 'HTTP_HOST' => "192.168.1.200"
    assert_nil request.domain
268

269 270
    request = stub_request 'HTTP_HOST' => "foo.192.168.1.200"
    assert_nil request.domain
271

272 273
    request = stub_request 'HTTP_HOST' => "192.168.1.200.com"
    assert_equal "200.com", request.domain
274 275
  end

276
  test "subdomains" do
277 278
    request = stub_request 'HTTP_HOST' => "www.rubyonrails.org"
    assert_equal %w( www ), request.subdomains
J
José Valim 已提交
279
    assert_equal "www", request.subdomain
280

281 282
    request = stub_request 'HTTP_HOST' => "www.rubyonrails.co.uk"
    assert_equal %w( www ), request.subdomains(2)
J
José Valim 已提交
283
    assert_equal "www", request.subdomain(2)
284

285 286
    request = stub_request 'HTTP_HOST' => "dev.www.rubyonrails.co.uk"
    assert_equal %w( dev www ), request.subdomains(2)
J
José Valim 已提交
287
    assert_equal "dev.www", request.subdomain(2)
288

289 290
    request = stub_request 'HTTP_HOST' => "dev.www.rubyonrails.co.uk", :tld_length => 2
    assert_equal %w( dev www ), request.subdomains
J
José Valim 已提交
291
    assert_equal "dev.www", request.subdomain
292

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

297 298
    request = stub_request 'HTTP_HOST' => "192.168.1.200"
    assert_equal [], request.subdomains
J
José Valim 已提交
299
    assert_equal "", request.subdomain
300

301 302
    request = stub_request 'HTTP_HOST' => "foo.192.168.1.200"
    assert_equal [], request.subdomains
J
José Valim 已提交
303
    assert_equal "", request.subdomain
304

305 306
    request = stub_request 'HTTP_HOST' => "192.168.1.200.com"
    assert_equal %w( 192 168 1 ), request.subdomains
J
José Valim 已提交
307
    assert_equal "192.168.1", request.subdomain
308

309 310
    request = stub_request 'HTTP_HOST' => nil
    assert_equal [], request.subdomains
J
José Valim 已提交
311
    assert_equal "", request.subdomain
312
  end
313
end
314

315
class RequestPort < BaseRequestTest
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
  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

342
  test "optional port" do
343
    request = stub_request 'HTTP_HOST' => 'www.example.org:80'
344
    assert_equal nil, request.optional_port
345

346
    request = stub_request 'HTTP_HOST' => 'www.example.org:8080'
347
    assert_equal 8080, request.optional_port
348
  end
349

350 351 352 353 354 355 356
  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
357
end
358

359
class RequestPath < BaseRequestTest
360
  test "full path" do
361
    request = stub_request 'SCRIPT_NAME' => '', 'PATH_INFO' => '/path/of/some/uri', 'QUERY_STRING' => 'mapped=1'
362 363
    assert_equal "/path/of/some/uri?mapped=1", request.fullpath
    assert_equal "/path/of/some/uri",          request.path_info
364

365
    request = stub_request 'SCRIPT_NAME' => '', 'PATH_INFO' => '/path/of/some/uri'
366 367
    assert_equal "/path/of/some/uri", request.fullpath
    assert_equal "/path/of/some/uri", request.path_info
368

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

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

377
    request = stub_request 'SCRIPT_NAME' => '/hieraki', 'PATH_INFO' => '/'
378 379
    assert_equal "/hieraki/", request.fullpath
    assert_equal "/",         request.path_info
380

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

385
    request = stub_request 'SCRIPT_NAME' => '/path', 'PATH_INFO' => '/of/some/uri', 'QUERY_STRING' => 'mapped=1'
386 387
    assert_equal "/path/of/some/uri?mapped=1", request.fullpath
    assert_equal "/of/some/uri",               request.path_info
388
  end
389

390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
  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
416
  test "host with default port" do
417 418
    request = stub_request 'HTTP_HOST' => 'rubyonrails.org:80'
    assert_equal "rubyonrails.org", request.host_with_port
419
  end
420

421
  test "host with non default port" do
422 423
    request = stub_request 'HTTP_HOST' => 'rubyonrails.org:81'
    assert_equal "rubyonrails.org:81", request.host_with_port
424
  end
425

426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 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
  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
  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

531 532 533
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 已提交
534
    assert request.local?
535 536 537
  end
end

538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568
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
569

570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
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
596

597 598 599 600
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
601
  end
602

603
  test "xml http request" do
604 605 606 607
    request = stub_request

    assert !request.xml_http_request?
    assert !request.xhr?
608

609 610 611
    request = stub_request 'HTTP_X_REQUESTED_WITH' => 'DefinitelyNotAjax1.0'
    assert !request.xml_http_request?
    assert !request.xhr?
612

613 614 615
    request = stub_request 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest'
    assert request.xml_http_request?
    assert request.xhr?
616
  end
617

618
  test "reports ssl" do
619 620
    assert !stub_request.ssl?
    assert stub_request('HTTPS' => 'on').ssl?
621 622
  end

623
  test "reports ssl when proxied via lighttpd" do
624
    assert stub_request('HTTP_X_FORWARDED_PROTO' => 'https').ssl?
625
  end
626

627 628 629 630 631
  test "scheme returns https when proxied" do
    request = stub_request 'rack.url_scheme' => 'http'
    assert !request.ssl?
    assert_equal 'http', request.scheme

632 633 634 635
    request = stub_request(
      'rack.url_scheme' => 'http',
      'HTTP_X_FORWARDED_PROTO' => 'https'
    )
636 637 638
    assert request.ssl?
    assert_equal 'https', request.scheme
  end
639
end
640

641
class RequestMethod < BaseRequestTest
642
  test "method returns environment's request method when it has not been
643
    overridden by middleware".squish do
644

645 646 647 648 649
    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
650 651 652
    end
  end

653 654 655 656 657 658 659 660 661 662 663 664
  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"]
  end

665
  test "invalid http method raises exception" do
666
    assert_raise(ActionController::UnknownHttpMethod) do
667
      stub_request('REQUEST_METHOD' => 'RANDOM_METHOD').request_method
668 669 670
    end
  end

G
Guo Xiang Tan 已提交
671 672 673
  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
674 675
  end

G
Guo Xiang Tan 已提交
676
  test "method raises exception on invalid HTTP method" do
677
    assert_raise(ActionController::UnknownHttpMethod) do
G
Guo Xiang Tan 已提交
678
      stub_request('rack.methodoverride.original_method' => '_RANDOM_METHOD').method
679
    end
680

G
Guo Xiang Tan 已提交
681 682
    assert_raise(ActionController::UnknownHttpMethod) do
      stub_request('REQUEST_METHOD' => '_RANDOM_METHOD').method
683 684
    end
  end
685

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701
  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

702
  test "post masquerading as patch" do
703 704 705 706 707
    request = stub_request(
      'REQUEST_METHOD' => 'PATCH',
      "rack.methodoverride.original_method" => "POST"
    )

708 709 710 711 712
    assert_equal "POST", request.method
    assert_equal "PATCH",  request.request_method
    assert request.patch?
  end

713
  test "post masquerading as put" do
714 715 716 717
    request = stub_request(
      'REQUEST_METHOD' => 'PUT',
      "rack.methodoverride.original_method" => "POST"
    )
718 719 720 721 722
    assert_equal "POST", request.method
    assert_equal "PUT",  request.request_method
    assert request.put?
  end

723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
  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
743
end
744

745
class RequestFormat < BaseRequestTest
746
  test "xml format" do
747 748 749
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => 'xml' })
    assert_equal Mime::XML, request.format
750
  end
751

752
  test "xhtml format" do
753 754 755
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => 'xhtml' })
    assert_equal Mime::HTML, request.format
756
  end
757

758
  test "txt format" do
759 760 761
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => 'txt' })
    assert_equal Mime::TEXT, request.format
762
  end
763

764
  test "XMLHttpRequest" do
765 766 767 768
    request = stub_request(
      'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest',
      'HTTP_ACCEPT' => [Mime::JS, Mime::HTML, Mime::XML, "text/xml", Mime::ALL].join(",")
    )
769 770 771
    request.expects(:parameters).at_least_once.returns({})
    assert request.xhr?
    assert_equal Mime::JS, request.format
772
  end
773

774
  test "can override format with parameter negative" do
775 776 777
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => :txt })
    assert !request.format.xml?
778
  end
779

780
  test "can override format with parameter positive" do
781 782 783
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => :xml })
    assert request.format.xml?
784 785
  end

786
  test "formats text/html with accept header" do
787
    request = stub_request 'HTTP_ACCEPT' => 'text/html'
788
    assert_equal [Mime::HTML], request.formats
789
  end
790

791
  test "formats blank with accept header" do
792 793
    request = stub_request 'HTTP_ACCEPT' => ''
    assert_equal [Mime::HTML], request.formats
794
  end
795

796 797
  test "formats XMLHttpRequest with accept header" do
    request = stub_request 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
798
    assert_equal [Mime::JS], request.formats
799
  end
800

801 802 803
  test "formats application/xml with accept header" do
    request = stub_request('CONTENT_TYPE' => 'application/xml; charset=UTF-8',
                           'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest")
804
    assert_equal [Mime::XML], request.formats
805
  end
806

807
  test "formats format:text with accept header" do
808 809
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => :txt })
810
    assert_equal [Mime::TEXT], request.formats
811
  end
812

813
  test "formats format:unknown with accept header" do
814 815
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => :unknown })
816
    assert_instance_of Mime::NullType, request.format
817 818
  end

819 820 821
  test "format is not nil with unknown format" do
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ format: :hello })
822 823 824 825
    assert request.format.nil?
    assert_not request.format.html?
    assert_not request.format.xml?
    assert_not request.format.json?
826
  end
827

J
Jarmo Isotalo 已提交
828 829 830 831 832 833
  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

834 835 836 837 838 839
  test "formats with xhr request" do
    request = stub_request 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
    request.expects(:parameters).at_least_once.returns({})
    assert_equal [Mime::JS], request.formats
  end

840
  test "ignore_accept_header" do
841
    old_ignore_accept_header = ActionDispatch::Request.ignore_accept_header
842 843 844 845 846 847 848
    ActionDispatch::Request.ignore_accept_header = true

    begin
      request = stub_request 'HTTP_ACCEPT' => 'application/xml'
      request.expects(:parameters).at_least_once.returns({})
      assert_equal [ Mime::HTML ], request.formats

J
José Valim 已提交
849 850 851 852 853 854 855 856 857 858 859 860
      request = stub_request 'HTTP_ACCEPT' => 'koz-asked/something-crazy'
      request.expects(:parameters).at_least_once.returns({})
      assert_equal [ Mime::HTML ], request.formats

      request = stub_request 'HTTP_ACCEPT' => '*/*;q=0.1'
      request.expects(:parameters).at_least_once.returns({})
      assert_equal [ Mime::HTML ], request.formats

      request = stub_request 'HTTP_ACCEPT' => 'application/jxw'
      request.expects(:parameters).at_least_once.returns({})
      assert_equal [ Mime::HTML ], request.formats

861 862 863 864 865 866 867 868 869 870
      request = stub_request 'HTTP_ACCEPT' => 'application/xml',
                             'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
      request.expects(:parameters).at_least_once.returns({})
      assert_equal [ Mime::JS ], request.formats

      request = stub_request 'HTTP_ACCEPT' => 'application/xml',
                             'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
      request.expects(:parameters).at_least_once.returns({:format => :json})
      assert_equal [ Mime::JSON ], request.formats
    ensure
871
      ActionDispatch::Request.ignore_accept_header = old_ignore_accept_header
872 873
    end
  end
874
end
875

876 877 878 879
class RequestMimeType < BaseRequestTest
  test "content type" do
    assert_equal Mime::HTML, stub_request('CONTENT_TYPE' => 'text/html').content_mime_type
  end
880

881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
  test "no content type" do
    assert_equal nil, stub_request.content_mime_type
  end

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

  test "content type with charset" do
    assert_equal Mime::XML, stub_request('CONTENT_TYPE' => 'application/xml; charset=UTF-8').content_mime_type
  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"
    )
902 903 904 905

    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])
906 907 908 909 910 911 912
  end

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

    assert_equal Mime::XML, request.negotiate_mime([Mime::XML, Mime::CSV])
915
  end
916
end
917

918 919 920 921 922 923 924 925 926 927 928
class RequestParameters < BaseRequestTest
  test "parameters" do
    request = stub_request
    request.expects(:request_parameters).at_least_once.returns({ "foo" => 1 })
    request.expects(:query_parameters).at_least_once.returns({ "bar" => 2 })

    assert_equal({"foo" => 1, "bar" => 2}, request.parameters)
    assert_equal({"foo" => 1}, request.request_parameters)
    assert_equal({"bar" => 2}, request.query_parameters)
  end

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

J
Jarmo Isotalo 已提交
932 933
    2.times do
      assert_raises(ActionController::BadRequest) do
934
        # rack will raise a Rack::Utils::ParameterTypeError when parsing this query string
J
Jarmo Isotalo 已提交
935 936
        request.parameters
      end
937
    end
938 939
  end

940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959
  test "parameters not accessible after rack parse error of invalid UTF8 character" do
    request = stub_request("QUERY_STRING" => "foo%81E=1")

    2.times do
      assert_raises(ActionController::BadRequest) do
        # rack will raise a Rack::Utils::InvalidParameterError when parsing this query string
        request.parameters
      end
    end
  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
960
      # rack will raise a Rack::Utils::ParameterTypeError when parsing this query string
961 962 963 964
      request.parameters
    end
  end

965 966 967 968
  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
969
      # rack will raise a Rack::Utils::ParameterTypeError when parsing this query string
970 971 972 973 974 975 976 977 978 979
      request.parameters
    end

    assert e.original_exception
    assert_equal e.original_exception.backtrace, e.backtrace
  end
end


class RequestParameterFilter < BaseRequestTest
980
  test "process parameter filter" do
981 982 983 984 985 986 987
    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'],
988
    [{'baz'=>[{'foo'=>'baz'}, "1"]}, {'baz'=>[{'foo'=>'[FILTERED]'}, "1"]}, [/foo/]]]
989 990

    test_hashes.each do |before_filter, after_filter, filter_words|
991 992
      parameter_filter = ActionDispatch::Http::ParameterFilter.new(filter_words)
      assert_equal after_filter, parameter_filter.filter(before_filter)
993

994 995
      filter_words << 'blah'
      filter_words << lambda { |key, value|
996
        value.reverse! if key =~ /bargain/
997
      }
998

999
      parameter_filter = ActionDispatch::Http::ParameterFilter.new(filter_words)
1000
      before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}}
1001
      after_filter['barg']  = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}}
1002

1003
      assert_equal after_filter, parameter_filter.filter(before_filter)
1004 1005
    end
  end
1006

1007
  test "filtered_parameters returns params filtered" do
1008 1009 1010 1011 1012 1013 1014 1015
    request = stub_request(
      'action_dispatch.request.parameters' => {
        'lifo' => 'Pratik',
        'amount' => '420',
        'step' => '1'
      },
      'action_dispatch.parameter_filter' => [:lifo, :amount]
    )
1016 1017 1018 1019 1020 1021 1022 1023

    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
1024 1025 1026 1027 1028 1029 1030 1031
    request = stub_request(
      'action_dispatch.request.parameters' => {
        'amount' => '420',
        'step' => '1'
      },
      "RAW_POST_DATA" => "yada yada",
      'action_dispatch.parameter_filter' => [:lifo, :amount]
    )
1032
    request = stub_request(request.filtered_env)
1033 1034 1035

    assert_equal "[FILTERED]", request.raw_post
    assert_equal "[FILTERED]", request.params["amount"]
1036
    assert_equal "1", request.params["step"]
1037 1038
  end

1039 1040
  test "filtered_path returns path with filtered query string" do
    %w(; &).each do |sep|
1041 1042
      request = stub_request(
        'QUERY_STRING' => %w(username=sikachu secret=bd4f21f api_key=b1bc3b3cd352f68d79d7).join(sep),
1043
        'PATH_INFO' => '/authenticate',
1044 1045
        'action_dispatch.parameter_filter' => [:secret, :api_key]
      )
1046 1047 1048 1049 1050 1051 1052

      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
1053 1054
    request = stub_request(
      'QUERY_STRING' => "secret=bd4f21f&genuine=%5BFILTERED%5D",
1055
      'PATH_INFO' => '/authenticate',
1056 1057
      'action_dispatch.parameter_filter' => [:secret]
    )
1058 1059

    path = request.filtered_path
1060
    assert_equal request.script_name + "/authenticate?secret=[FILTERED]&genuine=%5BFILTERED%5D", path
1061 1062 1063
  end

  test "filtered_path should preserve duplication of keys in query string" do
1064 1065
    request = stub_request(
      'QUERY_STRING' => "username=sikachu&secret=bd4f21f&username=fxn",
1066
      'PATH_INFO' => '/authenticate',
1067 1068
      'action_dispatch.parameter_filter' => [:secret]
    )
1069 1070

    path = request.filtered_path
1071
    assert_equal request.script_name + "/authenticate?username=sikachu&secret=[FILTERED]&username=fxn", path
1072 1073 1074
  end

  test "filtered_path should ignore searchparts" do
1075 1076
    request = stub_request(
      'QUERY_STRING' => "secret",
1077
      'PATH_INFO' => '/authenticate',
1078 1079
      'action_dispatch.parameter_filter' => [:secret]
    )
1080 1081

    path = request.filtered_path
1082
    assert_equal request.script_name + "/authenticate?secret", path
1083
  end
1084
end
1085

1086
class RequestEtag < BaseRequestTest
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124
  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
1125
end
1126

R
Rafael Mendonça França 已提交
1127
class RequestVariant < BaseRequestTest
Ł
Łukasz Strzałkowski 已提交
1128 1129
  test "setting variant" do
    request = stub_request
L
Lukasz Strzalkowski 已提交
1130

Ł
Łukasz Strzałkowski 已提交
1131
    request.variant = :mobile
L
Lukasz Strzalkowski 已提交
1132 1133 1134 1135
    assert_equal [:mobile], request.variant

    request.variant = [:phone, :tablet]
    assert_equal [:phone, :tablet], request.variant
1136 1137 1138 1139 1140 1141 1142 1143

    assert_raise ArgumentError do
      request.variant = [:phone, "tablet"]
    end

    assert_raise ArgumentError do
      request.variant = "yolo"
    end
Ł
Łukasz Strzałkowski 已提交
1144 1145 1146 1147 1148 1149 1150 1151
  end

  test "setting variant with non symbol value" do
    request = stub_request
    assert_raise ArgumentError do
      request.variant = "mobile"
    end
  end
1152
end