1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/actionpack/test/dispatch/request_test.rb
Kasper Timm Hansen 5bd29afeb4
Skip cookie comma separation test
Rack updated the RFC they're adhering to when parsing cookies, now no
longer including commas.

There's still an open question as mentioned in:
https://github.com/rails/rails/issues/38420

However, the resilience test is no longer as well needed as it once was
and we can move forward separately. If not, this is easily revertible.
2020-02-10 01:48:47 +01:00

1292 lines
46 KiB
Ruby
Raw Blame History

# frozen_string_literal: true
require "abstract_unit"
class BaseRequestTest < ActiveSupport::TestCase
def setup
@env = {
:ip_spoofing_check => true,
"rack.input" => "foo"
}
@original_tld_length = ActionDispatch::Http::URL.tld_length
end
def teardown
ActionDispatch::Http::URL.tld_length = @original_tld_length
end
def url_for(options = {})
options = { host: "www.example.com" }.merge!(options)
ActionDispatch::Http::URL.url_for(options)
end
private
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)
ActionDispatch::Http::URL.tld_length = env.delete(:tld_length) if env.key?(:tld_length)
ip_app.call(env)
env = @env.merge(env)
ActionDispatch::Request.new(env)
end
end
class RequestUrlFor < BaseRequestTest
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")
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=////")
assert_equal "http://www.example.com", url_for
assert_equal "http://api.example.com", url_for(subdomain: "api")
assert_equal "http://example.com", url_for(subdomain: false)
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" })
assert_equal "http://www.example.com?params=", url_for(params: "")
assert_equal "http://www.example.com?params=1", url_for(params: 1)
end
end
class RequestIP < BaseRequestTest
test "remote ip" do
request = stub_request "REMOTE_ADDR" => "1.2.3.4"
assert_equal "1.2.3.4", request.remote_ip
request = stub_request "REMOTE_ADDR" => "1.2.3.4,3.4.5.6"
assert_equal "3.4.5.6", request.remote_ip
request = stub_request "REMOTE_ADDR" => "1.2.3.4",
"HTTP_X_FORWARDED_FOR" => "3.4.5.6"
assert_equal "3.4.5.6", request.remote_ip
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
request = stub_request "REMOTE_ADDR" => "127.0.0.1",
"HTTP_X_FORWARDED_FOR" => "172.31.4.4, 10.0.0.1"
assert_equal "172.31.4.4", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "3.4.5.6,unknown"
assert_equal "3.4.5.6", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "3.4.5.6,172.16.0.1"
assert_equal "3.4.5.6", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "3.4.5.6,192.168.0.1"
assert_equal "3.4.5.6", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "3.4.5.6,10.0.0.1"
assert_equal "3.4.5.6", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "172.31.4.4, 10.0.0.1"
assert_equal "172.31.4.4", request.remote_ip
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
request = stub_request "HTTP_X_FORWARDED_FOR" => "3.4.5.6,127.0.0.1"
assert_equal "3.4.5.6", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "unknown,192.168.0.1"
assert_equal "192.168.0.1", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "9.9.9.9, 3.4.5.6, 172.31.4.4, 10.0.0.1"
assert_equal "3.4.5.6", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "not_ip_address"
assert_nil request.remote_ip
request = stub_request "REMOTE_ADDR" => "1.2.3.4"
assert_equal "1.2.3.4", request.remote_ip
request.remote_ip = "2.3.4.5"
assert_equal "2.3.4.5", request.remote_ip
end
test "remote ip spoof detection" do
request = stub_request "HTTP_X_FORWARDED_FOR" => "1.1.1.1",
"HTTP_CLIENT_IP" => "2.2.2.2"
e = assert_raise(ActionDispatch::RemoteIp::IpSpoofAttackError) {
request.remote_ip
}
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)
end
test "remote ip with spoof detection disabled" do
request = stub_request "HTTP_X_FORWARDED_FOR" => "1.1.1.1",
"HTTP_CLIENT_IP" => "2.2.2.2",
:ip_spoofing_check => false
assert_equal "1.1.1.1", request.remote_ip
end
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
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
request = stub_request "REMOTE_ADDR" => "fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334"
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
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
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
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
request = stub_request "HTTP_X_FORWARDED_FOR" => "unknown,::1"
assert_equal "::1", request.remote_ip
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"
assert_equal "fe80:0000:0000:0000:0202:b3ff:fe1e:8329", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "FE00::, FDFF::"
assert_equal "FE00::", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "not_ip_address"
assert_nil request.remote_ip
end
test "remote ip v6 spoof detection" do
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)
end
test "remote ip v6 spoof detection disabled" do
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
test "remote ip with user specified trusted proxies String" do
@trusted_proxies = "67.205.106.73"
request = stub_request "REMOTE_ADDR" => "3.4.5.6",
"HTTP_X_FORWARDED_FOR" => "67.205.106.73"
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" => "67.205.106.73"
assert_equal "67.205.106.73", request.remote_ip
request = stub_request "REMOTE_ADDR" => "67.205.106.73,3.4.5.6",
"HTTP_X_FORWARDED_FOR" => "67.205.106.73"
assert_equal "3.4.5.6", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "67.205.106.73,unknown"
assert_equal "67.205.106.73", request.remote_ip # change
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
end
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"
assert_equal "fe80:0000:0000:0000:0202:b3ff:fe1e:8329", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "unknown,fe80:0000:0000:0000:0202:b3ff:fe1e:8329"
assert_equal "fe80:0000:0000:0000:0202:b3ff:fe1e:8329", 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"
assert_equal "2001:0db8:85a3:0000:0000:8a2e:0370:7334", request.remote_ip
end
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
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
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
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
request = stub_request("REMOTE_ADDR" => "127.0.0.1")
assert_equal "127.0.0.1", request.remote_ip
end
end
class RequestDomain < BaseRequestTest
test "domains" do
request = stub_request "HTTP_HOST" => "192.168.1.200"
assert_nil request.domain
request = stub_request "HTTP_HOST" => "foo.192.168.1.200"
assert_nil request.domain
request = stub_request "HTTP_HOST" => "192.168.1.200.com"
assert_equal "200.com", request.domain
request = stub_request "HTTP_HOST" => "www.rubyonrails.org"
assert_equal "rubyonrails.org", request.domain
request = stub_request "HTTP_HOST" => "www.rubyonrails.co.uk"
assert_equal "rubyonrails.co.uk", request.domain(2)
request = stub_request "HTTP_HOST" => "www.rubyonrails.co.uk", :tld_length => 2
assert_equal "rubyonrails.co.uk", request.domain
end
test "subdomains" do
request = stub_request "HTTP_HOST" => "foobar.foobar.com"
assert_equal %w( foobar ), request.subdomains
assert_equal "foobar", request.subdomain
request = stub_request "HTTP_HOST" => "192.168.1.200"
assert_equal [], request.subdomains
assert_equal "", request.subdomain
request = stub_request "HTTP_HOST" => "foo.192.168.1.200"
assert_equal [], request.subdomains
assert_equal "", request.subdomain
request = stub_request "HTTP_HOST" => "192.168.1.200.com"
assert_equal %w( 192 168 1 ), request.subdomains
assert_equal "192.168.1", request.subdomain
request = stub_request "HTTP_HOST" => nil
assert_equal [], request.subdomains
assert_equal "", request.subdomain
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
end
end
class RequestPort < BaseRequestTest
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_not_predicate request, :ssl?
assert_predicate request, :standard_port?
request = stub_request "HTTPS" => "on"
assert_predicate request, :ssl?
assert_predicate request, :standard_port?
request = stub_request "HTTP_HOST" => "www.example.org:8080"
assert_not_predicate request, :ssl?
assert_not_predicate request, :standard_port?
request = stub_request "HTTP_HOST" => "www.example.org:8443", "HTTPS" => "on"
assert_predicate request, :ssl?
assert_not_predicate request, :standard_port?
end
test "optional port" do
request = stub_request "HTTP_HOST" => "www.example.org:80"
assert_nil request.optional_port
request = stub_request "HTTP_HOST" => "www.example.org:8080"
assert_equal 8080, request.optional_port
end
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
test "server port" do
request = stub_request "SERVER_PORT" => "8080"
assert_equal 8080, request.server_port
request = stub_request "SERVER_PORT" => "80"
assert_equal 80, request.server_port
request = stub_request "SERVER_PORT" => ""
assert_equal 0, request.server_port
end
end
class RequestPath < BaseRequestTest
test "full path" do
request = stub_request "SCRIPT_NAME" => "", "PATH_INFO" => "/path/of/some/uri", "QUERY_STRING" => "mapped=1"
assert_equal "/path/of/some/uri?mapped=1", request.fullpath
assert_equal "/path/of/some/uri", request.path_info
request = stub_request "SCRIPT_NAME" => "", "PATH_INFO" => "/path/of/some/uri"
assert_equal "/path/of/some/uri", request.fullpath
assert_equal "/path/of/some/uri", request.path_info
request = stub_request "SCRIPT_NAME" => "", "PATH_INFO" => "/"
assert_equal "/", request.fullpath
assert_equal "/", request.path_info
request = stub_request "SCRIPT_NAME" => "", "PATH_INFO" => "/", "QUERY_STRING" => "m=b"
assert_equal "/?m=b", request.fullpath
assert_equal "/", request.path_info
request = stub_request "SCRIPT_NAME" => "/hieraki", "PATH_INFO" => "/"
assert_equal "/hieraki/", request.fullpath
assert_equal "/", request.path_info
request = stub_request "SCRIPT_NAME" => "/collaboration/hieraki", "PATH_INFO" => "/books/edit/2"
assert_equal "/collaboration/hieraki/books/edit/2", request.fullpath
assert_equal "/books/edit/2", request.path_info
request = stub_request "SCRIPT_NAME" => "/path", "PATH_INFO" => "/of/some/uri", "QUERY_STRING" => "mapped=1"
assert_equal "/path/of/some/uri?mapped=1", request.fullpath
assert_equal "/of/some/uri", request.path_info
end
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
test "host without specifying port" do
request = stub_request "HTTP_HOST" => "rubyonrails.org"
assert_equal "rubyonrails.org", request.host_with_port
end
test "host with default port" do
request = stub_request "HTTP_HOST" => "rubyonrails.org:80"
assert_equal "rubyonrails.org", request.host_with_port
end
test "host with non default port" do
request = stub_request "HTTP_HOST" => "rubyonrails.org:81"
assert_equal "rubyonrails.org:81", request.host_with_port
end
test "raw without specifying port" do
request = stub_request "HTTP_HOST" => "rubyonrails.org"
assert_equal "rubyonrails.org", request.raw_host_with_port
end
test "raw host with default port" do
request = stub_request "HTTP_HOST" => "rubyonrails.org:80"
assert_equal "rubyonrails.org:80", request.raw_host_with_port
end
test "raw host with non default port" do
request = stub_request "HTTP_HOST" => "rubyonrails.org:81"
assert_equal "rubyonrails.org:81", request.raw_host_with_port
end
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
request = stub_request "HTTP_X_FORWARDED_HOST" => "", "HTTP_HOST" => "rubyonrails.org"
assert_equal "rubyonrails.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_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
class LocalhostTest < BaseRequestTest
test "IPs that match localhost" do
request = stub_request("REMOTE_IP" => "127.1.1.1", "REMOTE_ADDR" => "127.1.1.1")
assert_predicate request, :local?
end
end
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
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
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
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
end
test "xml http request" do
request = stub_request
assert_not_predicate request, :xml_http_request?
assert_not_predicate request, :xhr?
request = stub_request "HTTP_X_REQUESTED_WITH" => "DefinitelyNotAjax1.0"
assert_not_predicate request, :xml_http_request?
assert_not_predicate request, :xhr?
request = stub_request "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"
assert_predicate request, :xml_http_request?
assert_predicate request, :xhr?
end
test "reports ssl" do
assert_not_predicate stub_request, :ssl?
assert_predicate stub_request("HTTPS" => "on"), :ssl?
end
test "reports ssl when proxied via lighttpd" do
assert_predicate stub_request("HTTP_X_FORWARDED_PROTO" => "https"), :ssl?
end
test "scheme returns https when proxied" do
request = stub_request "rack.url_scheme" => "http"
assert_not_predicate request, :ssl?
assert_equal "http", request.scheme
request = stub_request(
"rack.url_scheme" => "http",
"HTTP_X_FORWARDED_PROTO" => "https"
)
assert_predicate request, :ssl?
assert_equal "https", request.scheme
end
end
class RequestMethod < BaseRequestTest
test "method returns environment's request method when it has not been
overridden by middleware".squish do
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
end
end
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"]
assert_predicate request, :get?
end
test "invalid http method raises exception" do
assert_raise(ActionController::UnknownHttpMethod) do
stub_request("REQUEST_METHOD" => "RANDOM_METHOD").request_method
end
end
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
end
test "method raises exception on invalid HTTP method" do
assert_raise(ActionController::UnknownHttpMethod) do
stub_request("rack.methodoverride.original_method" => "_RANDOM_METHOD").method
end
assert_raise(ActionController::UnknownHttpMethod) do
stub_request("REQUEST_METHOD" => "_RANDOM_METHOD").method
end
end
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
test "post masquerading as patch" do
request = stub_request(
"REQUEST_METHOD" => "PATCH",
"rack.methodoverride.original_method" => "POST"
)
assert_equal "POST", request.method
assert_equal "PATCH", request.request_method
assert_predicate request, :patch?
end
test "post masquerading as put" do
request = stub_request(
"REQUEST_METHOD" => "PUT",
"rack.methodoverride.original_method" => "POST"
)
assert_equal "POST", request.method
assert_equal "PUT", request.request_method
assert_predicate request, :put?
end
test "post uneffected by local inflections" do
existing_acronyms = ActiveSupport::Inflector.inflections.acronyms.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_predicate request, :post?
ensure
# Reset original acronym set
ActiveSupport::Inflector.inflections do |inflect|
inflect.send(:instance_variable_set, "@acronyms", existing_acronyms)
inflect.send(:define_acronym_regex_patterns)
end
end
end
end
class RequestFormat < BaseRequestTest
test "xml format" do
request = stub_request "QUERY_STRING" => "format=xml"
assert_equal Mime[:xml], request.format
end
test "xhtml format" do
request = stub_request "QUERY_STRING" => "format=xhtml"
assert_equal Mime[:html], request.format
end
test "txt format" do
request = stub_request "QUERY_STRING" => "format=txt"
assert_equal Mime[:text], request.format
end
test "XMLHttpRequest" do
request = stub_request(
"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
"HTTP_ACCEPT" => [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(","),
"QUERY_STRING" => ""
)
assert_predicate request, :xhr?
assert_equal Mime[:js], request.format
end
test "can override format with parameter negative" do
request = stub_request("QUERY_STRING" => "format=txt")
assert_not_predicate request.format, :xml?
end
test "can override format with parameter positive" do
request = stub_request("QUERY_STRING" => "format=xml")
assert_predicate request.format, :xml?
end
test "formats text/html with accept header" do
request = stub_request "HTTP_ACCEPT" => "text/html"
assert_equal [Mime[:html]], request.formats
end
test "formats blank with accept header" do
request = stub_request "HTTP_ACCEPT" => ""
assert_equal [Mime[:html]], request.formats
end
test "formats XMLHttpRequest with accept header" do
request = stub_request "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"
assert_equal [Mime[:js]], request.formats
end
test "formats application/xml with accept header" do
request = stub_request("CONTENT_TYPE" => "application/xml; charset=UTF-8",
"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest")
assert_equal [Mime[:xml]], request.formats
end
test "formats format:text with accept header" do
request = stub_request("QUERY_STRING" => "format=txt")
assert_equal [Mime[:text]], request.formats
end
test "formats format:unknown with accept header" do
request = stub_request("QUERY_STRING" => "format=unknown")
assert_instance_of Mime::NullType, request.format
end
test "format is not nil with unknown format" do
request = stub_request("QUERY_STRING" => "format=hello")
assert_nil request.format
assert_not_predicate request.format, :html?
assert_not_predicate request.format, :xml?
assert_not_predicate request.format, :json?
end
test "format does not throw exceptions when malformed GET parameters" do
request = stub_request("QUERY_STRING" => "x[y]=1&x[y][][w]=2")
assert request.formats
assert_predicate request.format, :html?
end
test "format does not throw exceptions when invalid POST parameters" do
body = "{record:{content:127.0.0.1}}"
request = stub_request(
"REQUEST_METHOD" => "POST",
"CONTENT_LENGTH" => body.length,
"CONTENT_TYPE" => "application/json",
"rack.input" => StringIO.new(body),
"action_dispatch.logger" => Logger.new(output = StringIO.new)
)
assert request.formats
assert request.format.html?
output.rewind && (err = output.read)
assert_match(/Error occurred while parsing request parameters/, err)
end
test "formats with xhr request" do
request = stub_request "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
"QUERY_STRING" => ""
assert_equal [Mime[:js]], request.formats
end
test "ignore_accept_header" do
old_ignore_accept_header = ActionDispatch::Request.ignore_accept_header
ActionDispatch::Request.ignore_accept_header = true
begin
request = stub_request "HTTP_ACCEPT" => "application/xml",
"QUERY_STRING" => ""
assert_equal [ Mime[:html] ], request.formats
request = stub_request "HTTP_ACCEPT" => "koz-asked/something-crazy",
"QUERY_STRING" => ""
assert_equal [ Mime[:html] ], request.formats
request = stub_request "HTTP_ACCEPT" => "*/*;q=0.1",
"QUERY_STRING" => ""
assert_equal [ Mime[:html] ], request.formats
request = stub_request "HTTP_ACCEPT" => "application/jxw",
"QUERY_STRING" => ""
assert_equal [ Mime[:html] ], request.formats
request = stub_request "HTTP_ACCEPT" => "application/xml",
"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
"QUERY_STRING" => ""
assert_equal [ Mime[:js] ], request.formats
request = stub_request "HTTP_ACCEPT" => "application/xml",
"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest",
"QUERY_STRING" => "format=json"
assert_equal [ Mime[:json] ], request.formats
ensure
ActionDispatch::Request.ignore_accept_header = old_ignore_accept_header
end
end
test "format taken from the path extension" do
request = stub_request "PATH_INFO" => "/foo.xml", "QUERY_STRING" => ""
assert_equal [Mime[:xml]], request.formats
request = stub_request "PATH_INFO" => "/foo.123", "QUERY_STRING" => ""
assert_equal [Mime[:html]], request.formats
end
test "formats from accept headers have higher precedence than path extension" do
request = stub_request "HTTP_ACCEPT" => "application/json",
"PATH_INFO" => "/foo.xml",
"QUERY_STRING" => ""
assert_equal [Mime[:json]], request.formats
end
end
class RequestMimeType < BaseRequestTest
test "content type" do
assert_equal Mime[:html], stub_request("CONTENT_TYPE" => "text/html").content_mime_type
end
test "no content type" do
assert_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"
)
assert_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])
end
test "negotiate_mime with content_type" do
request = stub_request(
"CONTENT_TYPE" => "application/xml; charset=UTF-8",
"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"
)
assert_equal Mime[:xml], request.negotiate_mime([Mime[:xml], Mime[:csv]])
end
end
class RequestParameters < BaseRequestTest
test "parameters" do
request = stub_request "CONTENT_TYPE" => "application/json",
"CONTENT_LENGTH" => 9,
"RAW_POST_DATA" => '{"foo":1}',
"QUERY_STRING" => "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
test "parameters not accessible after rack parse error" do
request = stub_request("QUERY_STRING" => "x[y]=1&x[y][][w]=2")
2.times do
assert_raises(ActionController::BadRequest) do
# rack will raise a Rack::Utils::ParameterTypeError when parsing this query string
request.parameters
end
end
end
test "path parameters with invalid UTF8 encoding" do
request = stub_request
err = assert_raises(ActionController::BadRequest) do
request.path_parameters = { foo: "\xBE" }
end
assert_predicate err.message, :valid_encoding?
assert_equal "Invalid path parameters: Invalid encoding for parameter: <20>", err.message
end
test "parameters not accessible after rack parse error of invalid UTF8 character" do
request = stub_request("QUERY_STRING" => "foo%81E=1")
assert_raises(ActionController::BadRequest) { request.parameters }
end
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 }
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
# rack will raise a Rack::Utils::ParameterTypeError when parsing this query string
request.parameters
end
end
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
# rack will raise a Rack::Utils::ParameterTypeError when parsing this query string
request.parameters
end
assert_not_nil e.cause
assert_equal e.cause.backtrace, e.backtrace
end
end
class RequestParameterFilter < BaseRequestTest
test "parameter filter is deprecated" do
assert_deprecated do
ActionDispatch::Http::ParameterFilter.new(["blah"])
end
end
test "filtered_parameters returns params filtered" do
request = stub_request(
"action_dispatch.request.parameters" => {
"lifo" => "Pratik",
"amount" => "420",
"step" => "1"
},
"action_dispatch.parameter_filter" => [:lifo, :amount]
)
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
request = stub_request(
"action_dispatch.request.parameters" => {
"amount" => "420",
"step" => "1"
},
"RAW_POST_DATA" => "yada yada",
"action_dispatch.parameter_filter" => [:lifo, :amount]
)
request = stub_request(request.filtered_env)
assert_equal "[FILTERED]", request.raw_post
assert_equal "[FILTERED]", request.params["amount"]
assert_equal "1", request.params["step"]
end
test "filtered_path returns path with filtered query string" do
%w(; &).each do |sep|
request = stub_request(
"QUERY_STRING" => %w(username=sikachu secret=bd4f21f api_key=b1bc3b3cd352f68d79d7).join(sep),
"PATH_INFO" => "/authenticate",
"action_dispatch.parameter_filter" => [:secret, :api_key]
)
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
request = stub_request(
"QUERY_STRING" => "secret=bd4f21f&genuine=%5BFILTERED%5D",
"PATH_INFO" => "/authenticate",
"action_dispatch.parameter_filter" => [:secret]
)
path = request.filtered_path
assert_equal request.script_name + "/authenticate?secret=[FILTERED]&genuine=%5BFILTERED%5D", path
end
test "filtered_path should preserve duplication of keys in query string" do
request = stub_request(
"QUERY_STRING" => "username=sikachu&secret=bd4f21f&username=fxn",
"PATH_INFO" => "/authenticate",
"action_dispatch.parameter_filter" => [:secret]
)
path = request.filtered_path
assert_equal request.script_name + "/authenticate?username=sikachu&secret=[FILTERED]&username=fxn", path
end
test "filtered_path should ignore searchparts" do
request = stub_request(
"QUERY_STRING" => "secret",
"PATH_INFO" => "/authenticate",
"action_dispatch.parameter_filter" => [:secret]
)
path = request.filtered_path
assert_equal request.script_name + "/authenticate?secret", path
end
end
class RequestEtag < BaseRequestTest
test "always matches *" do
request = stub_request("HTTP_IF_NONE_MATCH" => "*")
assert_equal "*", request.if_none_match
assert_equal ["*"], request.if_none_match_etags
assert request.etag_matches?('"strong"')
assert request.etag_matches?('W/"weak"')
assert_not request.etag_matches?(nil)
end
test "doesn't match absent If-None-Match" do
request = stub_request
assert_nil request.if_none_match
assert_equal [], request.if_none_match_etags
assert_not request.etag_matches?("foo")
assert_not request.etag_matches?(nil)
end
test "matches opaque ETag validators without unquoting" 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"')
assert_not 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
end
class RequestVariant < BaseRequestTest
def setup
super
@request = stub_request
end
test "setting variant to a symbol" do
@request.variant = :phone
assert_predicate @request.variant, :phone?
assert_not_predicate @request.variant, :tablet?
assert @request.variant.any?(:phone, :tablet)
assert_not @request.variant.any?(:tablet, :desktop)
end
test "setting variant to an array of symbols" do
@request.variant = [:phone, :tablet]
assert_predicate @request.variant, :phone?
assert_predicate @request.variant, :tablet?
assert_not_predicate @request.variant, :desktop?
assert @request.variant.any?(:tablet, :desktop)
assert_not @request.variant.any?(:desktop, :watch)
end
test "clearing variant" do
@request.variant = nil
assert_empty @request.variant
assert_not_predicate @request.variant, :phone?
assert_not @request.variant.any?(:phone, :tablet)
end
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
assert_raise ArgumentError do
@request.variant = [:phone, "tablet"]
end
end
end
class RequestFormData < BaseRequestTest
test "media_type is from the FORM_DATA_MEDIA_TYPES array" do
assert_predicate stub_request("CONTENT_TYPE" => "application/x-www-form-urlencoded"), :form_data?
assert_predicate stub_request("CONTENT_TYPE" => "multipart/form-data"), :form_data?
end
test "media_type is not from the FORM_DATA_MEDIA_TYPES array" do
assert_not_predicate stub_request("CONTENT_TYPE" => "application/xml"), :form_data?
assert_not_predicate 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_not_predicate request, :form_data?
end
end
class EarlyHintsRequestTest < BaseRequestTest
def setup
super
@env["rack.early_hints"] = lambda { |links| links }
@request = stub_request
end
test "when early hints is set in the env link headers are sent" do
early_hints = @request.send_early_hints("Link" => "</style.css>; rel=preload; as=style\n</script.js>; rel=preload")
expected_hints = { "Link" => "</style.css>; rel=preload; as=style\n</script.js>; rel=preload" }
assert_equal expected_hints, early_hints
end
end