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

3
class RequestTest < ActiveSupport::TestCase
4
  def setup
5
    ActionController::Base.relative_url_root = nil
6 7
  end

8 9 10 11
  def teardown
    ActionController::Base.relative_url_root = nil
  end

12
  test "remote ip" do
13 14
    request = stub_request 'REMOTE_ADDR' => '1.2.3.4'
    assert_equal '1.2.3.4', request.remote_ip
15

16 17
    request = stub_request 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6'
    assert_equal '1.2.3.4', request.remote_ip
18

19 20 21
    request = stub_request 'REMOTE_ADDR' => '1.2.3.4',
      'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
    assert_equal '1.2.3.4', request.remote_ip
22

23 24 25
    request = stub_request 'REMOTE_ADDR' => '127.0.0.1',
      'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
    assert_equal '3.4.5.6', request.remote_ip
J
Jeremy Kemper 已提交
26

27 28
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,3.4.5.6'
    assert_equal '3.4.5.6', request.remote_ip
29

30 31
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '172.16.0.1,3.4.5.6'
    assert_equal '3.4.5.6', request.remote_ip
J
Jeremy Kemper 已提交
32

33 34
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '192.168.0.1,3.4.5.6'
    assert_equal '3.4.5.6', request.remote_ip
35

36 37
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '10.0.0.1,3.4.5.6'
    assert_equal '3.4.5.6', request.remote_ip
38

39 40
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '10.0.0.1, 10.0.0.1, 3.4.5.6'
    assert_equal '3.4.5.6', request.remote_ip
41

42 43
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '127.0.0.1,3.4.5.6'
    assert_equal '3.4.5.6', request.remote_ip
44

45 46
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,192.168.0.1'
    assert_equal 'unknown', request.remote_ip
47

48 49
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 10.0.0.1, 172.31.4.4'
    assert_equal '3.4.5.6', request.remote_ip
50

51 52
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '1.1.1.1',
                           'HTTP_CLIENT_IP'       => '2.2.2.2'
53
    e = assert_raise(ActionController::ActionControllerError) {
54
      request.remote_ip
J
Jeremy Kemper 已提交
55 56
    }
    assert_match /IP spoofing attack/, e.message
57 58
    assert_match /HTTP_X_FORWARDED_FOR="1.1.1.1"/, e.message
    assert_match /HTTP_CLIENT_IP="2.2.2.2"/, e.message
J
Jeremy Kemper 已提交
59

60 61 62 63 64 65
    # turn IP Spoofing detection off.
    # This is useful for sites that are aimed at non-IP clients.  The typical
    # example is WAP.  Since the cellular network is not IP based, it's a
    # leap of faith to assume that their proxies are ever going to set the
    # HTTP_CLIENT_IP/HTTP_X_FORWARDED_FOR headers properly.
    ActionController::Base.ip_spoofing_check = false
66 67 68
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '1.1.1.1',
                           'HTTP_CLIENT_IP'       => '2.2.2.2'
    assert_equal '2.2.2.2', request.remote_ip
69 70
    ActionController::Base.ip_spoofing_check = true

71 72
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '8.8.8.8, 9.9.9.9'
    assert_equal '9.9.9.9', request.remote_ip
73 74
  end

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
  test "remote ip with user specified trusted proxies" do
    ActionController::Base.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

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

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

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

    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,67.205.106.73'
    assert_equal 'unknown', request.remote_ip

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

    ActionController::Base.trusted_proxies = nil
  end

103
  test "domains" do
104 105
    request = stub_request 'HTTP_HOST' => 'www.rubyonrails.org'
    assert_equal "rubyonrails.org", request.domain
106

107 108
    request = stub_request 'HTTP_HOST' => "www.rubyonrails.co.uk"
    assert_equal "rubyonrails.co.uk", request.domain(2)
109

110 111
    request = stub_request 'HTTP_HOST' => "192.168.1.200"
    assert_nil request.domain
112

113 114
    request = stub_request 'HTTP_HOST' => "foo.192.168.1.200"
    assert_nil request.domain
115

116 117
    request = stub_request 'HTTP_HOST' => "192.168.1.200.com"
    assert_equal "200.com", request.domain
118 119
  end

120
  test "subdomains" do
121 122
    request = stub_request 'HTTP_HOST' => "www.rubyonrails.org"
    assert_equal %w( www ), request.subdomains
123

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

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

130 131
    request = stub_request 'HTTP_HOST' => "foobar.foobar.com"
    assert_equal %w( foobar ), request.subdomains
132

133 134
    request = stub_request 'HTTP_HOST' => "192.168.1.200"
    assert_equal [], request.subdomains
135

136 137
    request = stub_request 'HTTP_HOST' => "foo.192.168.1.200"
    assert_equal [], request.subdomains
138

139 140
    request = stub_request 'HTTP_HOST' => "192.168.1.200.com"
    assert_equal %w( 192 168 1 ), request.subdomains
141

142 143
    request = stub_request 'HTTP_HOST' => nil
    assert_equal [], request.subdomains
144
  end
145

146
  test "port string" do
147 148
    request = stub_request 'HTTP_HOST' => 'www.example.org:80'
    assert_equal "", request.port_string
149

150 151
    request = stub_request 'HTTP_HOST' => 'www.example.org:8080'
    assert_equal ":8080", request.port_string
152
  end
153

154
  test "request uri" do
155 156 157
    request = stub_request 'REQUEST_URI' => "http://www.rubyonrails.org/path/of/some/uri?mapped=1"
    assert_equal "/path/of/some/uri?mapped=1", request.request_uri
    assert_equal "/path/of/some/uri",          request.path
158

159 160 161
    request = stub_request 'REQUEST_URI' => "http://www.rubyonrails.org/path/of/some/uri"
    assert_equal "/path/of/some/uri", request.request_uri
    assert_equal "/path/of/some/uri", request.path
162

163 164 165
    request = stub_request 'REQUEST_URI' => "/path/of/some/uri"
    assert_equal "/path/of/some/uri", request.request_uri
    assert_equal "/path/of/some/uri", request.path
166

167 168 169
    request = stub_request 'REQUEST_URI' => "/"
    assert_equal "/", request.request_uri
    assert_equal "/", request.path
170

171 172 173
    request = stub_request 'REQUEST_URI' => "/?m=b"
    assert_equal "/?m=b", request.request_uri
    assert_equal "/",     request.path
174

175 176 177
    request = stub_request 'REQUEST_URI' => "/", 'SCRIPT_NAME' => '/dispatch.cgi'
    assert_equal "/", request.request_uri
    assert_equal "/", request.path
178

179
    ActionController::Base.relative_url_root = "/hieraki"
180 181 182
    request = stub_request 'REQUEST_URI' => "/hieraki/", 'SCRIPT_NAME' => "/hieraki/dispatch.cgi"
    assert_equal "/hieraki/", request.request_uri
    assert_equal "/",         request.path
183
    ActionController::Base.relative_url_root = nil
184

185
    ActionController::Base.relative_url_root = "/collaboration/hieraki"
186 187 188 189
    request = stub_request 'REQUEST_URI' => "/collaboration/hieraki/books/edit/2",
      'SCRIPT_NAME' => "/collaboration/hieraki/dispatch.cgi"
    assert_equal "/collaboration/hieraki/books/edit/2", request.request_uri
    assert_equal "/books/edit/2",                       request.path
190
    ActionController::Base.relative_url_root = nil
191

192
    # The following tests are for when REQUEST_URI is not supplied (as in IIS)
193 194 195 196 197
    request = stub_request 'PATH_INFO'   => "/path/of/some/uri?mapped=1",
                           'SCRIPT_NAME' => nil,
                           'REQUEST_URI' => nil
    assert_equal "/path/of/some/uri?mapped=1", request.request_uri
    assert_equal "/path/of/some/uri",          request.path
198

199
    ActionController::Base.relative_url_root = '/path'
200 201 202 203 204
    request = stub_request 'PATH_INFO'   => "/path/of/some/uri?mapped=1",
                           'SCRIPT_NAME' => "/path/dispatch.rb",
                           'REQUEST_URI' => nil
    assert_equal "/path/of/some/uri?mapped=1", request.request_uri
    assert_equal "/of/some/uri",               request.path
205
    ActionController::Base.relative_url_root = nil
206

207 208 209 210 211
    request = stub_request 'PATH_INFO'   => "/path/of/some/uri",
                           'SCRIPT_NAME' => nil,
                           'REQUEST_URI' => nil
    assert_equal "/path/of/some/uri", request.request_uri
    assert_equal "/path/of/some/uri", request.path
212

213 214 215
    request = stub_request 'PATH_INFO' => '/', 'REQUEST_URI' => nil
    assert_equal "/", request.request_uri
    assert_equal "/", request.path
216

217 218 219
    request = stub_request 'PATH_INFO' => '/?m=b', 'REQUEST_URI' => nil
    assert_equal "/?m=b", request.request_uri
    assert_equal "/",     request.path
220

221 222 223 224 225
    request = stub_request 'PATH_INFO'   => "/",
                           'SCRIPT_NAME' => "/dispatch.cgi",
                           'REQUEST_URI' => nil
    assert_equal "/", request.request_uri
    assert_equal "/", request.path
226

227
    ActionController::Base.relative_url_root = '/hieraki'
228 229 230 231 232
    request = stub_request 'PATH_INFO'   => "/hieraki/",
                           'SCRIPT_NAME' => "/hieraki/dispatch.cgi",
                           'REQUEST_URI' => nil
    assert_equal "/hieraki/", request.request_uri
    assert_equal "/",         request.path
233
    ActionController::Base.relative_url_root = nil
234

235
    request = stub_request 'REQUEST_URI' => '/hieraki/dispatch.cgi'
236
    ActionController::Base.relative_url_root = '/hieraki'
237
    assert_equal "/dispatch.cgi", request.path
238
    ActionController::Base.relative_url_root = nil
239

240
    request = stub_request 'REQUEST_URI' => '/hieraki/dispatch.cgi'
241
    ActionController::Base.relative_url_root = '/foo'
242
    assert_equal "/hieraki/dispatch.cgi", request.path
243
    ActionController::Base.relative_url_root = nil
244 245

    # This test ensures that Rails uses REQUEST_URI over PATH_INFO
246
    ActionController::Base.relative_url_root = nil
247 248 249 250 251
    request = stub_request 'REQUEST_URI' => "/some/path",
                           'PATH_INFO'   => "/another/path",
                           'SCRIPT_NAME' => "/dispatch.cgi"
    assert_equal "/some/path", request.request_uri
    assert_equal "/some/path", request.path
252
  end
253

254

255
  test "host with default port" do
256 257
    request = stub_request 'HTTP_HOST' => 'rubyonrails.org:80'
    assert_equal "rubyonrails.org", request.host_with_port
258
  end
259

260
  test "host with non default port" do
261 262
    request = stub_request 'HTTP_HOST' => 'rubyonrails.org:81'
    assert_equal "rubyonrails.org:81", request.host_with_port
263
  end
264

265
  test "server software" do
266 267
    request = stub_request
    assert_equal nil, request.server_software
268

269 270
    request = stub_request 'SERVER_SOFTWARE' => 'Apache3.422'
    assert_equal 'apache', request.server_software
271

272 273
    request = stub_request 'SERVER_SOFTWARE' => 'lighttpd(1.1.4)'
    assert_equal 'lighttpd', request.server_software
274
  end
275

276
  test "xml http request" do
277 278 279 280
    request = stub_request

    assert !request.xml_http_request?
    assert !request.xhr?
281

282 283 284
    request = stub_request 'HTTP_X_REQUESTED_WITH' => 'DefinitelyNotAjax1.0'
    assert !request.xml_http_request?
    assert !request.xhr?
285

286 287 288
    request = stub_request 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest'
    assert request.xml_http_request?
    assert request.xhr?
289
  end
290

291
  test "reports ssl" do
292 293 294 295 296
    request = stub_request
    assert !request.ssl?

    request = stub_request 'HTTPS' => 'on'
    assert request.ssl?
297 298
  end

299
  test "reports ssl when proxied via lighttpd" do
300 301 302 303 304
    request = stub_request
    assert !request.ssl?

    request = stub_request 'HTTP_X_FORWARDED_PROTO' => 'https'
    assert request.ssl?
305
  end
306

307
  test "symbolized request methods" do
308
    [:get, :post, :put, :delete].each do |method|
309 310
      request = stub_request 'REQUEST_METHOD' => method.to_s.upcase
      assert_equal method, request.method
311 312 313
    end
  end

314
  test "invalid http method raises exception" do
315
    assert_raise(ActionController::UnknownHttpMethod) do
316 317
      request = stub_request 'REQUEST_METHOD' => 'RANDOM_METHOD'
      request.request_method
318 319 320
    end
  end

321
  test "allow method hacking on post" do
322
    [:get, :options, :put, :post, :delete].each do |method|
323
      request = stub_request "REQUEST_METHOD" => method.to_s.upcase
324
      assert_equal(method == :head ? :get : method, request.method)
325 326 327
    end
  end

328
  test "invalid method hacking on post raises exception" do
329 330 331
    assert_raise(ActionController::UnknownHttpMethod) do
      request = stub_request "REQUEST_METHOD" => "_RANDOM_METHOD"
      request.request_method
332 333 334
    end
  end

335
  test "restrict method hacking" do
336
    [:get, :put, :delete].each do |method|
337
      request = stub_request 'REQUEST_METHOD' => method.to_s.upcase,
338
        'action_dispatch.request.request_parameters' => { :_method => 'put' }
339
      assert_equal method, request.method
340 341
    end
  end
342

343
  test "head masquerading as get" do
344
    request = stub_request 'REQUEST_METHOD' => 'GET', "rack.methodoverride.original_method" => "HEAD"
345 346 347
    assert_equal :get, request.method
    assert request.get?
    assert request.head?
348
  end
349

350
  test "xml format" do
351 352 353
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => 'xml' })
    assert_equal Mime::XML, request.format
354
  end
355

356
  test "xhtml format" do
357 358 359
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => 'xhtml' })
    assert_equal Mime::HTML, request.format
360
  end
361

362
  test "txt format" do
363 364 365
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => 'txt' })
    assert_equal Mime::TEXT, request.format
366
  end
367

368
  test "XMLHttpRequest" do
369 370 371 372 373 374
    request = stub_request 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest',
                           'HTTP_ACCEPT' =>
                             [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(",")
    request.expects(:parameters).at_least_once.returns({})
    assert request.xhr?
    assert_equal Mime::JS, request.format
375
  end
376

377
  test "content type" do
378 379
    request = stub_request 'CONTENT_TYPE' => 'text/html'
    assert_equal Mime::HTML, request.content_type
380 381
  end

382
  test "can override format with parameter" do
383 384 385 386 387 388 389
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => :txt })
    assert !request.format.xml?

    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => :xml })
    assert request.format.xml?
390 391
  end

392
  test "no content type" do
393 394
    request = stub_request
    assert_equal nil, request.content_type
395
  end
396

397
  test "content type is XML" do
398 399
    request = stub_request 'CONTENT_TYPE' => 'application/xml'
    assert_equal Mime::XML, request.content_type
400 401
  end

402
  test "content type with charset" do
403 404
    request = stub_request 'CONTENT_TYPE' => 'application/xml; charset=UTF-8'
    assert_equal Mime::XML, request.content_type
405
  end
406

407
  test "user agent" do
408 409
    request = stub_request 'HTTP_USER_AGENT' => 'TestAgent'
    assert_equal 'TestAgent', request.user_agent
410
  end
411

412
  test "parameters" do
413 414 415
    request = stub_request
    request.stubs(:request_parameters).returns({ "foo" => 1 })
    request.stubs(:query_parameters).returns({ "bar" => 2 })
416

417 418 419 420 421
    assert_equal({"foo" => 1, "bar" => 2}, request.parameters)
    assert_equal({"foo" => 1}, request.request_parameters)
    assert_equal({"bar" => 2}, request.query_parameters)
  end

422
  test "formats with accept header" do
423 424 425
    request = stub_request 'HTTP_ACCEPT' => 'text/html'
    request.expects(:parameters).at_least_once.returns({})
    assert_equal [ Mime::HTML ], request.formats
426

427 428 429 430 431 432 433 434
    request = stub_request 'CONTENT_TYPE' => 'application/xml; charset=UTF-8',
                           'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
    request.expects(:parameters).at_least_once.returns({})
    assert_equal with_set(Mime::XML), request.formats

    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => :txt })
    assert_equal with_set(Mime::TEXT), request.formats
435 436 437 438

    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => :unknown })
    assert request.formats.empty?
439 440 441
  end

  test "negotiate_mime" do
442 443 444 445 446 447 448 449 450 451 452 453 454
    request = stub_request 'HTTP_ACCEPT' => 'text/html',
                           'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"

    request.expects(:parameters).at_least_once.returns({})

    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])

    request = stub_request 'CONTENT_TYPE' => 'application/xml; charset=UTF-8',
                           'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
    request.expects(:parameters).at_least_once.returns({})
    assert_equal Mime::XML, request.negotiate_mime([Mime::XML, Mime::CSV])
455
  end
456 457 458 459 460

  class FilterRequest < ActionDispatch::Request
  end

  test "filter_parameters raises error without arguments" do
461
    assert_raises RuntimeError do
462
      FilterRequest.filter_parameters
463
    end
464 465 466 467 468
  end
  
  test "process parameter filter" do
    request = FilterRequest.new({})

469 470 471 472 473 474 475 476 477 478
    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'],
    [{'baz'=>[{'foo'=>'baz'}]}, {'baz'=>[{'foo'=>'[FILTERED]'}]}, %w(foo)]]

    test_hashes.each do |before_filter, after_filter, filter_words|
479 480
      FilterRequest.filter_parameters(*filter_words)
      assert_equal after_filter, request.send(:process_parameter_filter, before_filter)
481 482

      filter_words.push('blah')
483 484

      FilterRequest.filter_parameters(*filter_words) do |key, value|
485 486 487 488
        value.reverse! if key =~ /bargain/
      end

      before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}}
489
      after_filter['barg']  = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}}
490

491
      assert_equal after_filter, request.send(:process_parameter_filter, before_filter)
492 493
    end
  end
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
  test "filtered_parameters returns params filtered" do
    FilterRequest.filter_parameters(:lifo, :amount)

    request = FilterRequest.new('action_dispatch.request.parameters' =>
      { 'lifo' => 'Pratik', 'amount' => '420', 'step' => '1' })

    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
    FilterRequest.filter_parameters(:lifo, :amount)

    request = FilterRequest.new('action_dispatch.request.parameters' =>
      { 'amount' => '420', 'step' => '1' }, "RAW_POST_DATA" => "yada yada")

    request = FilterRequest.new(request.filtered_env)

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

520 521 522
protected

  def stub_request(env={})
523
    ActionDispatch::Request.new(env)
524
  end
525

526
  def with_set(*args)
527
    args
528 529
  end

530 531 532 533 534 535
  def with_accept_header(value)
    ActionController::Base.use_accept_header, old = value, ActionController::Base.use_accept_header
    yield
  ensure
    ActionController::Base.use_accept_header = old
  end
536
end