Skip to content

Commit 1521bc3

Browse files
committed
added support for basic auth, preserve host, and prevent transfer-encoding header from messing up response
1 parent 1089a5e commit 1521bc3

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

lib/rack/reverse_proxy.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class ReverseProxy
66
def initialize(app = nil, &b)
77
@app = app || lambda { [404, [], []] }
88
@paths = {}
9+
@opts = {:preserve_host => false}
910
instance_eval &b if block_given?
1011
end
1112

@@ -21,7 +22,7 @@ def call(env)
2122
headers[$1] = value
2223
end
2324
}
24-
headers['HOST'] = uri.host
25+
headers['HOST'] = uri.host if @opts[:preserve_host]
2526

2627
session = Net::HTTP.new(uri.host, uri.port)
2728
session.use_ssl = (uri.scheme == 'https')
@@ -31,8 +32,10 @@ def call(env)
3132
case m
3233
when "GET", "HEAD", "DELETE", "OPTIONS", "TRACE"
3334
req = Net::HTTP.const_get(m.capitalize).new(uri.request_uri, headers)
35+
req.basic_auth @opts[:username], @opts[:password] if @opts[:username] and @opts[:password]
3436
when "PUT", "POST"
3537
req = Net::HTTP.const_get(m.capitalize).new(uri.request_uri, headers)
38+
req.basic_auth @opts[:username], @opts[:password] if @opts[:username] and @opts[:password]
3639
req.content_length = rackreq.body.length
3740
req.body_stream = rackreq.body
3841
else
@@ -70,6 +73,8 @@ def create_response_headers http_response
7073
response_headers = Rack::Utils::HeaderHash.new(http_response.to_hash)
7174
# handled by Rack
7275
response_headers.delete('status')
76+
# TODO: figure out how to handle chunked responses
77+
response_headers.delete('transfer-encoding')
7378
# TODO: Verify Content Length, and required Rack headers
7479
response_headers
7580
end
@@ -91,9 +96,10 @@ def get_uri(url, matcher, path)
9196
end
9297
end
9398

94-
def reverse_proxy matcher, url
99+
def reverse_proxy matcher, url, opts={}
95100
raise GenericProxyURI.new(url) if matcher.is_a?(String) && URI(url).class == URI::Generic
96101
@paths.merge!(matcher => url)
102+
@opts.merge!(opts)
97103
end
98104
end
99105

spec/rack/reverse_proxy_spec.rb

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def dummy_app
1515
describe "as middleware" do
1616
def app
1717
Rack::ReverseProxy.new(dummy_app) do
18-
reverse_proxy '/test', 'http://example.com/'
18+
reverse_proxy '/test', 'http://example.com/', {:preserve_host => true}
1919
end
2020
end
2121

@@ -37,12 +37,46 @@ def app
3737
last_response.headers['Status'].should == nil
3838
end
3939

40+
it "the response header should never transfer-encoding" do
41+
stub_request(:any, 'example.com/test/stuff').to_return(:headers => {'transfer-encoding' => 'Chunked'})
42+
get '/test/stuff'
43+
last_response.headers['transfer-encoding'].should == nil
44+
end
45+
4046
it "should set the Host header" do
4147
stub_request(:any, 'example.com/test/stuff')
4248
get '/test/stuff'
4349
a_request(:get, 'http://example.com/test/stuff').with(:headers => {"Host" => "example.com"}).should have_been_made
4450
end
4551

52+
describe "with preserve host turned off" do
53+
def app
54+
Rack::ReverseProxy.new(dummy_app) do
55+
reverse_proxy '/test', 'http://example.com/'
56+
end
57+
end
58+
59+
it "should not set the Host header" do
60+
stub_request(:any, 'example.com/test/stuff')
61+
get '/test/stuff'
62+
a_request(:get, 'http://example.com/test/stuff').should have_been_made
63+
end
64+
end
65+
66+
describe "with basic auth turned on" do
67+
def app
68+
Rack::ReverseProxy.new(dummy_app) do
69+
reverse_proxy '/test', 'http://example.com/', {:username => "joe", :password => "shmoe"}
70+
end
71+
end
72+
73+
it "should make request with basic auth" do
74+
stub_request(:get, "http://joe:[email protected]/test/stuff").to_return(:body => "secured content")
75+
get '/test/stuff'
76+
last_response.body.should == "secured content"
77+
end
78+
end
79+
4680
describe "with ambiguous routes" do
4781
def app
4882
Rack::ReverseProxy.new(dummy_app) do

0 commit comments

Comments
 (0)