Skip to content
Permalink
Browse files

allow headers and env to be passed in `IntegrationTest`.

Closes #6513.
  • Loading branch information...
senny committed Mar 13, 2013
1 parent e2a5de2 commit 9af59b2468e4ad6c3c2ca89f90968fdcaa417aba
@@ -1,5 +1,16 @@
## Rails 4.0.0 (unreleased) ##

* `ActionDispatch::IntegrationTest` allows headers and rack env
variables to be passed when performing requests.
Fixes #6513.

Example:

get "/success", {}, "HTTP_REFERER" => "http://test.com/",
"Host" => "http://test.com"

*Yves Senn*

* Http::Headers respects headers that are not prefixed with HTTP_

*Yves Senn*
@@ -12,9 +12,11 @@ class Headers
HEADER_REGEXP = /\A[A-Za-z-]+\z/

include Enumerable
attr_reader :env

def initialize(env = {})
@env = env
@env = {}
merge!(env)
end

def [](key)
@@ -36,6 +38,18 @@ def each(&block)
@env.each(&block)
end

def merge(headers_or_env)
headers = Http::Headers.new(env.dup)
headers.merge!(headers_or_env)
headers
end

def merge!(headers_or_env)
headers_or_env.each do |key, value|
self[env_name(key)] = value
end
end

private
def env_name(key)
if key =~ HEADER_REGEXP
@@ -17,7 +17,7 @@ module RequestHelpers
# a Hash, or a String that is appropriately encoded
# (<tt>application/x-www-form-urlencoded</tt> or
# <tt>multipart/form-data</tt>).
# - +headers+: Additional headers to pass, as a Hash. The headers will be
# - +headers_or_env+: Additional headers to pass, as a Hash. The headers will be
# merged into the Rack env hash.
#
# This method returns a Response object, which one can use to
@@ -28,44 +28,44 @@ module RequestHelpers
#
# You can also perform POST, PATCH, PUT, DELETE, and HEAD requests with
# +#post+, +#patch+, +#put+, +#delete+, and +#head+.
def get(path, parameters = nil, headers = nil)
process :get, path, parameters, headers
def get(path, parameters = nil, headers_or_env = nil)
process :get, path, parameters, headers_or_env
end

# Performs a POST request with the given parameters. See +#get+ for more
# details.
def post(path, parameters = nil, headers = nil)
process :post, path, parameters, headers
def post(path, parameters = nil, headers_or_env = nil)
process :post, path, parameters, headers_or_env
end

# Performs a PATCH request with the given parameters. See +#get+ for more
# details.
def patch(path, parameters = nil, headers = nil)
process :patch, path, parameters, headers
def patch(path, parameters = nil, headers_or_env = nil)
process :patch, path, parameters, headers_or_env
end

# Performs a PUT request with the given parameters. See +#get+ for more
# details.
def put(path, parameters = nil, headers = nil)
process :put, path, parameters, headers
def put(path, parameters = nil, headers_or_env = nil)
process :put, path, parameters, headers_or_env
end

# Performs a DELETE request with the given parameters. See +#get+ for
# more details.
def delete(path, parameters = nil, headers = nil)
process :delete, path, parameters, headers
def delete(path, parameters = nil, headers_or_env = nil)
process :delete, path, parameters, headers_or_env
end

# Performs a HEAD request with the given parameters. See +#get+ for more
# details.
def head(path, parameters = nil, headers = nil)
process :head, path, parameters, headers
def head(path, parameters = nil, headers_or_env = nil)
process :head, path, parameters, headers_or_env
end

# Performs a OPTIONS request with the given parameters. See +#get+ for
# more details.
def options(path, parameters = nil, headers = nil)
process :options, path, parameters, headers
def options(path, parameters = nil, headers_or_env = nil)
process :options, path, parameters, headers_or_env
end

# Performs an XMLHttpRequest request with the given parameters, mirroring
@@ -74,11 +74,11 @@ def options(path, parameters = nil, headers = nil)
# The request_method is +:get+, +:post+, +:patch+, +:put+, +:delete+ or
# +:head+; the parameters are +nil+, a hash, or a url-encoded or multipart
# string; the headers are a hash.
def xml_http_request(request_method, path, parameters = nil, headers = nil)
headers ||= {}
headers['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
headers['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
process(request_method, path, parameters, headers)
def xml_http_request(request_method, path, parameters = nil, headers_or_env = nil)
headers_or_env ||= {}
headers_or_env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
headers_or_env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
process(request_method, path, parameters, headers_or_env)
end
alias xhr :xml_http_request

@@ -95,40 +95,40 @@ def follow_redirect!
# redirect. Note that the redirects are followed until the response is
# not a redirect--this means you may run into an infinite loop if your
# redirect loops back to itself.
def request_via_redirect(http_method, path, parameters = nil, headers = nil)
process(http_method, path, parameters, headers)
def request_via_redirect(http_method, path, parameters = nil, headers_or_env = nil)
process(http_method, path, parameters, headers_or_env)
follow_redirect! while redirect?
status
end

# Performs a GET request, following any subsequent redirect.
# See +request_via_redirect+ for more information.
def get_via_redirect(path, parameters = nil, headers = nil)
request_via_redirect(:get, path, parameters, headers)
def get_via_redirect(path, parameters = nil, headers_or_env = nil)
request_via_redirect(:get, path, parameters, headers_or_env)
end

# Performs a POST request, following any subsequent redirect.
# See +request_via_redirect+ for more information.
def post_via_redirect(path, parameters = nil, headers = nil)
request_via_redirect(:post, path, parameters, headers)
def post_via_redirect(path, parameters = nil, headers_or_env = nil)
request_via_redirect(:post, path, parameters, headers_or_env)
end

# Performs a PATCH request, following any subsequent redirect.
# See +request_via_redirect+ for more information.
def patch_via_redirect(path, parameters = nil, headers = nil)
request_via_redirect(:patch, path, parameters, headers)
def patch_via_redirect(path, parameters = nil, headers_or_env = nil)
request_via_redirect(:patch, path, parameters, headers_or_env)
end

# Performs a PUT request, following any subsequent redirect.
# See +request_via_redirect+ for more information.
def put_via_redirect(path, parameters = nil, headers = nil)
request_via_redirect(:put, path, parameters, headers)
def put_via_redirect(path, parameters = nil, headers_or_env = nil)
request_via_redirect(:put, path, parameters, headers_or_env)
end

# Performs a DELETE request, following any subsequent redirect.
# See +request_via_redirect+ for more information.
def delete_via_redirect(path, parameters = nil, headers = nil)
request_via_redirect(:delete, path, parameters, headers)
def delete_via_redirect(path, parameters = nil, headers_or_env = nil)
request_via_redirect(:delete, path, parameters, headers_or_env)
end
end

@@ -268,8 +268,8 @@ def _mock_session
end

# Performs the actual request.
def process(method, path, parameters = nil, rack_env = nil)
rack_env ||= {}
def process(method, path, parameters = nil, headers_or_env = nil)
rack_env = Http::Headers.new(headers_or_env || {}).env
if path =~ %r{://}
location = URI.parse(path)
https! URI::HTTPS === location if location.scheme
@@ -573,6 +573,21 @@ def test_failed_get
def test_generate_url_without_controller
assert_equal 'http://www.example.com/foo', url_for(:controller => "foo")
end

def test_pass_headers
get "/success", {}, "Referer" => "http://www.example.com/foo", "Host" => "http://nohost.com"

assert_equal "http://nohost.com", @request.env["HTTP_HOST"]
assert_equal "http://www.example.com/foo", @request.env["HTTP_REFERER"]
end

def test_pass_env
get "/success", {}, "HTTP_REFERER" => "http://test.com/", "HTTP_HOST" => "http://test.com"

assert_equal "http://test.com", @request.env["HTTP_HOST"]
assert_equal "http://test.com/", @request.env["HTTP_REFERER"]
end

end

class ApplicationIntegrationTest < ActionDispatch::IntegrationTest
@@ -8,7 +8,23 @@ class HeaderTest < ActiveSupport::TestCase
)
end

test "each" do
test "#new with mixed headers and env" do
headers = ActionDispatch::Http::Headers.new(
"Content-Type" => "application/json",
"HTTP_REFERER" => "/some/page",
"Host" => "http://test.com")

assert_equal({"CONTENT_TYPE" => "application/json",
"HTTP_REFERER" => "/some/page",
"HTTP_HOST" => "http://test.com"}, headers.env)
end

test "#env returns the headers as env variables" do
assert_equal({"CONTENT_TYPE" => "text/plain",
"HTTP_REFERER" => "/some/page"}, @headers.env)
end

test "#each iterates through the env variables" do
headers = []
@headers.each { |pair| headers << pair }
assert_equal [["CONTENT_TYPE", "text/plain"],
@@ -54,4 +70,31 @@ class HeaderTest < ActiveSupport::TestCase
assert_equal "text/plain", @headers.fetch("content-type", nil)
assert_equal "not found", @headers.fetch("not-found", "not found")
end

test "#merge! headers with mutation" do
@headers.merge!("Host" => "http://example.test",
"Content-Type" => "text/html")
assert_equal({"HTTP_HOST" => "http://example.test",
"CONTENT_TYPE" => "text/html",
"HTTP_REFERER" => "/some/page"}, @headers.env)
end

test "#merge! env with mutation" do
@headers.merge!("HTTP_HOST" => "http://first.com",
"CONTENT_TYPE" => "text/html")
assert_equal({"HTTP_HOST" => "http://first.com",
"CONTENT_TYPE" => "text/html",
"HTTP_REFERER" => "/some/page"}, @headers.env)
end

test "merge without mutation" do
combined = @headers.merge("HTTP_HOST" => "http://example.com",
"CONTENT_TYPE" => "text/html")
assert_equal({"HTTP_HOST" => "http://example.com",
"CONTENT_TYPE" => "text/html",
"HTTP_REFERER" => "/some/page"}, combined.env)

assert_equal({"CONTENT_TYPE" => "text/plain",
"HTTP_REFERER" => "/some/page"}, @headers.env)
end
end

0 comments on commit 9af59b2

Please sign in to comment.
You can’t perform that action at this time.