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

3
class RequestTest < ActiveSupport::TestCase
4
  test "remote ip" do
5 6
    request = stub_request 'REMOTE_ADDR' => '1.2.3.4'
    assert_equal '1.2.3.4', request.remote_ip
7

8 9
    request = stub_request 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6'
    assert_equal '1.2.3.4', request.remote_ip
10

11 12 13
    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
14

15 16 17
    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 已提交
18

19 20
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,3.4.5.6'
    assert_equal '3.4.5.6', request.remote_ip
21

22 23
    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 已提交
24

25 26
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '192.168.0.1,3.4.5.6'
    assert_equal '3.4.5.6', request.remote_ip
27

28 29
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '10.0.0.1,3.4.5.6'
    assert_equal '3.4.5.6', request.remote_ip
30

31 32
    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
33

34 35
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '127.0.0.1,3.4.5.6'
    assert_equal '3.4.5.6', request.remote_ip
36

37 38
    request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,192.168.0.1'
    assert_equal 'unknown', request.remote_ip
39

40 41
    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
42

43 44
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '1.1.1.1',
                           'HTTP_CLIENT_IP'       => '2.2.2.2'
45
    e = assert_raise(ActionController::ActionControllerError) {
46
      request.remote_ip
J
Jeremy Kemper 已提交
47 48
    }
    assert_match /IP spoofing attack/, e.message
49 50
    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 已提交
51

52 53 54 55 56 57
    # 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
58 59 60
    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
61 62
    ActionController::Base.ip_spoofing_check = true

63 64
    request = stub_request 'HTTP_X_FORWARDED_FOR' => '8.8.8.8, 9.9.9.9'
    assert_equal '9.9.9.9', request.remote_ip
65 66
  end

67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
  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

95
  test "domains" do
96 97
    request = stub_request 'HTTP_HOST' => 'www.rubyonrails.org'
    assert_equal "rubyonrails.org", request.domain
98

99 100
    request = stub_request 'HTTP_HOST' => "www.rubyonrails.co.uk"
    assert_equal "rubyonrails.co.uk", request.domain(2)
101

102 103
    request = stub_request 'HTTP_HOST' => "192.168.1.200"
    assert_nil request.domain
104

105 106
    request = stub_request 'HTTP_HOST' => "foo.192.168.1.200"
    assert_nil request.domain
107

108 109
    request = stub_request 'HTTP_HOST' => "192.168.1.200.com"
    assert_equal "200.com", request.domain
110 111
  end

112
  test "subdomains" do
113 114
    request = stub_request 'HTTP_HOST' => "www.rubyonrails.org"
    assert_equal %w( www ), request.subdomains
115

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

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

122 123
    request = stub_request 'HTTP_HOST' => "foobar.foobar.com"
    assert_equal %w( foobar ), request.subdomains
124

125 126
    request = stub_request 'HTTP_HOST' => "192.168.1.200"
    assert_equal [], request.subdomains
127

128 129
    request = stub_request 'HTTP_HOST' => "foo.192.168.1.200"
    assert_equal [], request.subdomains
130

131 132
    request = stub_request 'HTTP_HOST' => "192.168.1.200.com"
    assert_equal %w( 192 168 1 ), request.subdomains
133

134 135
    request = stub_request 'HTTP_HOST' => nil
    assert_equal [], request.subdomains
136
  end
137

138
  test "port string" do
139 140
    request = stub_request 'HTTP_HOST' => 'www.example.org:80'
    assert_equal "", request.port_string
141

142 143
    request = stub_request 'HTTP_HOST' => 'www.example.org:8080'
    assert_equal ":8080", request.port_string
144
  end
145

146
  test "request uri" do
147 148 149
    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
150

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

155 156 157
    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
158

159 160 161
    request = stub_request 'REQUEST_URI' => "/"
    assert_equal "/", request.request_uri
    assert_equal "/", request.path
162

163 164 165
    request = stub_request 'REQUEST_URI' => "/?m=b"
    assert_equal "/?m=b", request.request_uri
    assert_equal "/",     request.path
166

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

171
    ActionController::Base.relative_url_root = "/hieraki"
172 173 174
    request = stub_request 'REQUEST_URI' => "/hieraki/", 'SCRIPT_NAME' => "/hieraki/dispatch.cgi"
    assert_equal "/hieraki/", request.request_uri
    assert_equal "/",         request.path
175
    ActionController::Base.relative_url_root = nil
176

177
    ActionController::Base.relative_url_root = "/collaboration/hieraki"
178 179 180 181
    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
182
    ActionController::Base.relative_url_root = nil
183

184
    # The following tests are for when REQUEST_URI is not supplied (as in IIS)
185 186 187 188 189
    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
190

191
    ActionController::Base.relative_url_root = '/path'
192 193 194 195 196
    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
197
    ActionController::Base.relative_url_root = nil
198

199 200 201 202 203
    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
204

205 206 207
    request = stub_request 'PATH_INFO' => '/', 'REQUEST_URI' => nil
    assert_equal "/", request.request_uri
    assert_equal "/", request.path
208

209 210 211
    request = stub_request 'PATH_INFO' => '/?m=b', 'REQUEST_URI' => nil
    assert_equal "/?m=b", request.request_uri
    assert_equal "/",     request.path
212

213 214 215 216 217
    request = stub_request 'PATH_INFO'   => "/",
                           'SCRIPT_NAME' => "/dispatch.cgi",
                           'REQUEST_URI' => nil
    assert_equal "/", request.request_uri
    assert_equal "/", request.path
218

219
    ActionController::Base.relative_url_root = '/hieraki'
220 221 222 223 224
    request = stub_request 'PATH_INFO'   => "/hieraki/",
                           'SCRIPT_NAME' => "/hieraki/dispatch.cgi",
                           'REQUEST_URI' => nil
    assert_equal "/hieraki/", request.request_uri
    assert_equal "/",         request.path
225
    ActionController::Base.relative_url_root = nil
226

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

232
    request = stub_request 'REQUEST_URI' => '/hieraki/dispatch.cgi'
233
    ActionController::Base.relative_url_root = '/foo'
234
    assert_equal "/hieraki/dispatch.cgi", request.path
235
    ActionController::Base.relative_url_root = nil
236 237

    # This test ensures that Rails uses REQUEST_URI over PATH_INFO
238
    ActionController::Base.relative_url_root = nil
239 240 241 242 243
    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
244
  end
245

246

247
  test "host with default port" do
248 249
    request = stub_request 'HTTP_HOST' => 'rubyonrails.org:80'
    assert_equal "rubyonrails.org", request.host_with_port
250
  end
251

252
  test "host with non default port" do
253 254
    request = stub_request 'HTTP_HOST' => 'rubyonrails.org:81'
    assert_equal "rubyonrails.org:81", request.host_with_port
255
  end
256

257
  test "server software" do
258 259
    request = stub_request
    assert_equal nil, request.server_software
260

261 262
    request = stub_request 'SERVER_SOFTWARE' => 'Apache3.422'
    assert_equal 'apache', request.server_software
263

264 265
    request = stub_request 'SERVER_SOFTWARE' => 'lighttpd(1.1.4)'
    assert_equal 'lighttpd', request.server_software
266
  end
267

268
  test "xml http request" do
269 270 271 272
    request = stub_request

    assert !request.xml_http_request?
    assert !request.xhr?
273

274 275 276
    request = stub_request 'HTTP_X_REQUESTED_WITH' => 'DefinitelyNotAjax1.0'
    assert !request.xml_http_request?
    assert !request.xhr?
277

278 279 280
    request = stub_request 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest'
    assert request.xml_http_request?
    assert request.xhr?
281
  end
282

283
  test "reports ssl" do
284 285 286 287 288
    request = stub_request
    assert !request.ssl?

    request = stub_request 'HTTPS' => 'on'
    assert request.ssl?
289 290
  end

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

    request = stub_request 'HTTP_X_FORWARDED_PROTO' => 'https'
    assert request.ssl?
297
  end
298

299
  test "symbolized request methods" do
300
    [:get, :post, :put, :delete].each do |method|
301 302
      request = stub_request 'REQUEST_METHOD' => method.to_s.upcase
      assert_equal method, request.method
303 304 305
    end
  end

306
  test "invalid http method raises exception" do
307
    assert_raise(ActionController::UnknownHttpMethod) do
308 309
      request = stub_request 'REQUEST_METHOD' => 'RANDOM_METHOD'
      request.request_method
310 311 312
    end
  end

313
  test "allow method hacking on post" do
314
    [:get, :options, :put, :post, :delete].each do |method|
315
      request = stub_request "REQUEST_METHOD" => method.to_s.upcase
316
      assert_equal(method == :head ? :get : method, request.method)
317 318 319
    end
  end

320
  test "invalid method hacking on post raises exception" do
321 322 323
    assert_raise(ActionController::UnknownHttpMethod) do
      request = stub_request "REQUEST_METHOD" => "_RANDOM_METHOD"
      request.request_method
324 325 326
    end
  end

327
  test "restrict method hacking" do
328
    [:get, :put, :delete].each do |method|
329
      request = stub_request 'REQUEST_METHOD' => method.to_s.upcase,
330
        'action_dispatch.request.request_parameters' => { :_method => 'put' }
331
      assert_equal method, request.method
332 333
    end
  end
334

335
  test "head masquerading as get" do
336
    request = stub_request 'REQUEST_METHOD' => 'GET', "rack.methodoverride.original_method" => "HEAD"
337 338 339
    assert_equal :get, request.method
    assert request.get?
    assert request.head?
340
  end
341

342
  test "xml format" do
343 344 345
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => 'xml' })
    assert_equal Mime::XML, request.format
346
  end
347

348
  test "xhtml format" do
349 350 351
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => 'xhtml' })
    assert_equal Mime::HTML, request.format
352
  end
353

354
  test "txt format" do
355 356 357
    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => 'txt' })
    assert_equal Mime::TEXT, request.format
358
  end
359

360
  test "XMLHttpRequest" do
361 362 363 364 365 366
    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
367
  end
368

369
  test "content type" do
370 371
    request = stub_request 'CONTENT_TYPE' => 'text/html'
    assert_equal Mime::HTML, request.content_type
372 373
  end

374
  test "can override format with parameter" do
375 376 377 378 379 380 381
    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?
382 383
  end

384
  test "no content type" do
385 386
    request = stub_request
    assert_equal nil, request.content_type
387
  end
388

389
  test "content type is XML" do
390 391
    request = stub_request 'CONTENT_TYPE' => 'application/xml'
    assert_equal Mime::XML, request.content_type
392 393
  end

394
  test "content type with charset" do
395 396
    request = stub_request 'CONTENT_TYPE' => 'application/xml; charset=UTF-8'
    assert_equal Mime::XML, request.content_type
397
  end
398

399
  test "user agent" do
400 401
    request = stub_request 'HTTP_USER_AGENT' => 'TestAgent'
    assert_equal 'TestAgent', request.user_agent
402
  end
403

404
  test "parameters" do
405 406 407
    request = stub_request
    request.stubs(:request_parameters).returns({ "foo" => 1 })
    request.stubs(:query_parameters).returns({ "bar" => 2 })
408

409 410 411 412 413
    assert_equal({"foo" => 1, "bar" => 2}, request.parameters)
    assert_equal({"foo" => 1}, request.request_parameters)
    assert_equal({"bar" => 2}, request.query_parameters)
  end

414
  test "formats with accept header" do
415 416 417
    request = stub_request 'HTTP_ACCEPT' => 'text/html'
    request.expects(:parameters).at_least_once.returns({})
    assert_equal [ Mime::HTML ], request.formats
418

419 420 421 422 423 424 425 426
    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
427 428 429 430

    request = stub_request
    request.expects(:parameters).at_least_once.returns({ :format => :unknown })
    assert request.formats.empty?
431 432 433
  end

  test "negotiate_mime" do
434 435 436 437 438 439 440 441 442 443 444 445 446
    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])
447
  end
448 449

  test "process parameter filter" do
450 451 452 453 454 455 456
    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'],
457
    [{'baz'=>[{'foo'=>'baz'}, "1"]}, {'baz'=>[{'foo'=>'[FILTERED]'}, "1"]}, [/foo/]]]
458 459

    test_hashes.each do |before_filter, after_filter, filter_words|
460
      request = stub_request('action_dispatch.parameter_filter' => filter_words)
461
      assert_equal after_filter, request.send(:process_parameter_filter, before_filter)
462

463 464
      filter_words << 'blah'
      filter_words << lambda { |key, value|
465
        value.reverse! if key =~ /bargain/
466
      }
467

468
      request = stub_request('action_dispatch.parameter_filter' => filter_words)
469
      before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}}
470
      after_filter['barg']  = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}}
471

472
      assert_equal after_filter, request.send(:process_parameter_filter, before_filter)
473 474
    end
  end
475

476
  test "filtered_parameters returns params filtered" do
477 478 479
    request = stub_request('action_dispatch.request.parameters' =>
      { 'lifo' => 'Pratik', 'amount' => '420', 'step' => '1' },
      'action_dispatch.parameter_filter' => [:lifo, :amount])
480 481 482 483 484 485 486 487

    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
488 489 490
    request = stub_request('action_dispatch.request.parameters' =>
      { 'amount' => '420', 'step' => '1' }, "RAW_POST_DATA" => "yada yada",
      'action_dispatch.parameter_filter' => [:lifo, :amount])
491

492
    request = stub_request(request.filtered_env)
493 494 495 496 497 498

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

499 500 501
protected

  def stub_request(env={})
502
    ActionDispatch::Request.new(env)
503
  end
504

505
  def with_set(*args)
506
    args
507 508
  end

509 510 511 512 513 514
  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
515
end