Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

added support for basic auth, preserve host, and prevent transfer-enc…

…oding header from messing up response
  • Loading branch information...
commit 1521bc34f4dfd5a1ee6b0f7586b674f113205e6a 1 parent 1089a5e
@rmanalan rmanalan authored
Showing with 43 additions and 3 deletions.
  1. +8 −2 lib/rack/reverse_proxy.rb
  2. +35 −1 spec/rack/reverse_proxy_spec.rb
View
10 lib/rack/reverse_proxy.rb
@@ -6,6 +6,7 @@ class ReverseProxy
def initialize(app = nil, &b)
@app = app || lambda { [404, [], []] }
@paths = {}
+ @opts = {:preserve_host => false}
instance_eval &b if block_given?
end
@@ -21,7 +22,7 @@ def call(env)
headers[$1] = value
end
}
- headers['HOST'] = uri.host
+ headers['HOST'] = uri.host if @opts[:preserve_host]
session = Net::HTTP.new(uri.host, uri.port)
session.use_ssl = (uri.scheme == 'https')
@@ -31,8 +32,10 @@ def call(env)
case m
when "GET", "HEAD", "DELETE", "OPTIONS", "TRACE"
req = Net::HTTP.const_get(m.capitalize).new(uri.request_uri, headers)
+ req.basic_auth @opts[:username], @opts[:password] if @opts[:username] and @opts[:password]
when "PUT", "POST"
req = Net::HTTP.const_get(m.capitalize).new(uri.request_uri, headers)
+ req.basic_auth @opts[:username], @opts[:password] if @opts[:username] and @opts[:password]
req.content_length = rackreq.body.length
req.body_stream = rackreq.body
else
@@ -70,6 +73,8 @@ def create_response_headers http_response
response_headers = Rack::Utils::HeaderHash.new(http_response.to_hash)
# handled by Rack
response_headers.delete('status')
+ # TODO: figure out how to handle chunked responses
+ response_headers.delete('transfer-encoding')
# TODO: Verify Content Length, and required Rack headers
response_headers
end
@@ -91,9 +96,10 @@ def get_uri(url, matcher, path)
end
end
- def reverse_proxy matcher, url
+ def reverse_proxy matcher, url, opts={}
raise GenericProxyURI.new(url) if matcher.is_a?(String) && URI(url).class == URI::Generic
@paths.merge!(matcher => url)
+ @opts.merge!(opts)
end
end
View
36 spec/rack/reverse_proxy_spec.rb
@@ -15,7 +15,7 @@ def dummy_app
describe "as middleware" do
def app
Rack::ReverseProxy.new(dummy_app) do
- reverse_proxy '/test', 'http://example.com/'
+ reverse_proxy '/test', 'http://example.com/', {:preserve_host => true}
end
end
@@ -37,12 +37,46 @@ def app
last_response.headers['Status'].should == nil
end
+ it "the response header should never transfer-encoding" do
+ stub_request(:any, 'example.com/test/stuff').to_return(:headers => {'transfer-encoding' => 'Chunked'})
+ get '/test/stuff'
+ last_response.headers['transfer-encoding'].should == nil
+ end
+
it "should set the Host header" do
stub_request(:any, 'example.com/test/stuff')
get '/test/stuff'
a_request(:get, 'http://example.com/test/stuff').with(:headers => {"Host" => "example.com"}).should have_been_made
end
+ describe "with preserve host turned off" do
+ def app
+ Rack::ReverseProxy.new(dummy_app) do
+ reverse_proxy '/test', 'http://example.com/'
+ end
+ end
+
+ it "should not set the Host header" do
+ stub_request(:any, 'example.com/test/stuff')
+ get '/test/stuff'
+ a_request(:get, 'http://example.com/test/stuff').should have_been_made
+ end
+ end
+
+ describe "with basic auth turned on" do
+ def app
+ Rack::ReverseProxy.new(dummy_app) do
+ reverse_proxy '/test', 'http://example.com/', {:username => "joe", :password => "shmoe"}
+ end
+ end
+
+ it "should make request with basic auth" do
+ stub_request(:get, "http://joe:shmoe@example.com/test/stuff").to_return(:body => "secured content")
+ get '/test/stuff'
+ last_response.body.should == "secured content"
+ end
+ end
+
describe "with ambiguous routes" do
def app
Rack::ReverseProxy.new(dummy_app) do
Please sign in to comment.
Something went wrong with that request. Please try again.