Skip to content

Commit

Permalink
Added support for manipulating the proxied headers
Browse files Browse the repository at this point in the history
  • Loading branch information
blakewatters committed Apr 12, 2012
1 parent 7e69842 commit d1b574b
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 1 deletion.
13 changes: 12 additions & 1 deletion lib/rack/reverse_proxy.rb
Expand Up @@ -27,6 +27,16 @@ def call(env)
headers['HOST'] = uri.host if all_opts[:preserve_host]
headers['X-Forwarded-Host'] = rackreq.host if all_opts[:x_forwarded_host]
puts "Proxying #{rackreq.url} => #{uri} (Headers: #{headers.inspect})" if all_opts[:debug]

if headers_opt = all_opts[:headers]
if headers_opt.is_a?(Proc)
headers = headers_opt.call(headers)
elsif headers_opt.is_a?(Hash)
headers.merge!(headers_opt)
else
$stderr.puts "Warning: :headers option provided with unsupported type '#{headers_opt.class}'. Expected a Hash or Proc"
end
end

session = Net::HTTP.new(uri.host, uri.port)
session.read_timeout=all_opts[:timeout] if all_opts[:timeout]
Expand All @@ -37,7 +47,8 @@ def call(env)
else
# DO NOT DO THIS IN PRODUCTION !!!
session.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
end

session.start { |http|
m = rackreq.request_method
case m
Expand Down
51 changes: 51 additions & 0 deletions spec/rack/reverse_proxy_spec.rb
Expand Up @@ -120,6 +120,57 @@ def app
get '/test/stuff'
end
end

describe "with headers dictionary provided" do
context 'when the header does not exist in the source request' do
def app
Rack::ReverseProxy.new(dummy_app) do
reverse_proxy '/test', 'http://example.com/', {:headers => {'X-EXAMPLE-HEADER' => 'A value'}}
end
end

it "should add the provided headers" do
stub_request(:any, 'example.com/test/stuff')
get '/test/stuff'
a_request(:get, 'http://example.com/test/stuff').with(:headers => {"X-EXAMPLE-HEADER" => "A value"}).should have_been_made
end
end

context 'when the header already appears in the source request' do
def app
Rack::ReverseProxy.new(dummy_app) do
reverse_proxy '/test', 'http://example.com/', {:headers => {'X-EXAMPLE-HEADER' => 'New value'}}
end
end

it "should replace the existing Headers value" do
headers = {'Accept'=>'*/*', 'Cookie'=>'', 'Host'=>'example.com', 'User-Agent'=>'Ruby',
'X-Example-Header'=>'New value', 'X-Forwarded-Host'=>'example.org'}
stub_request(:any, 'example.com/test/stuff').with(:headers => headers)
get '/test/stuff', {}, {"X-EXAMPLE-HEADER" => "Original value"}
a_request(:get, 'http://example.com/test/stuff').with(:headers => {"X-EXAMPLE-HEADER" => "New value"}).should have_been_made
end
end
end

describe 'with headers proc provided' do
def app
Rack::ReverseProxy.new(dummy_app) do
reverse_proxy('/test', 'http://example.com/', :headers => lambda do |headers|
headers['X-FORWARDED-FOR'].gsub!(', 127.0.0.1', '') if headers['X-FORWARDED-FOR']
headers
end)
end
end

it "should yield the headers to the proc for manipulation" do
headers = {'Accept'=>'*/*', 'Cookie'=>'', 'Host'=>'example.com', 'User-Agent'=>'Ruby',
'X-Forwarded_For'=>'174.254.197.191', 'X-Forwarded-Host'=>'example.org'}
stub_request(:any, 'example.com/test/stuff').with(:headers => headers)
get '/test/stuff', {}, {'HTTP_X_Forwarded_For'=>'174.254.197.191, 127.0.0.1'}
a_request(:get, 'http://example.com/test/stuff').with(:headers => {"X-Forwarded-For" => "174.254.197.191"}).should have_been_made
end
end

describe "with ambiguous routes and all matching" do
def app
Expand Down

0 comments on commit d1b574b

Please sign in to comment.