Skip to content

Commit 59e7fe4

Browse files
committed
Merge pull request jaswope#16 from pigoz/ssl_fixes
https fixes and a new feature
2 parents 0562207 + 6fc82f1 commit 59e7fe4

File tree

3 files changed

+50
-2
lines changed

3 files changed

+50
-2
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ run app
5151
* `:password` password for basic auth
5252
* `:matching` is a global only option, if set to :first the first matched url will be requested (no ambigous error). Default: :all.
5353
* `:timeout` seconds to timout the requests
54+
* `:force_ssl` redirects to ssl version, if not already using it (requires `:replace_response_host`). Default: false.
5455

5556
### Sample usage in a Ruby on Rails app
5657

lib/rack_reverse_proxy/middleware.rb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ def proxy(env, source_request, rule)
6060

6161
options = @global_options.dup.merge(rule.options)
6262

63+
if options[:force_ssl] && options[:replace_response_host] &&
64+
source_request.scheme == "http"
65+
rewrite_uri(uri, source_request)
66+
uri.scheme = "https"
67+
return [301, { "Location" => uri.to_s }, ""]
68+
end
69+
6370
# Initialize request
6471
target_request = Net::HTTP.const_get(
6572
source_request.request_method.capitalize
@@ -115,8 +122,7 @@ def proxy(env, source_request, rule)
115122
# Replace the location header with the proxy domain
116123
if response_headers["Location"] && options[:replace_response_host]
117124
response_location = URI(response_headers["location"])
118-
response_location.host = source_request.host
119-
response_location.port = source_request.port
125+
rewrite_uri(response_location, source_request)
120126
response_headers["Location"] = response_location.to_s
121127
end
122128

@@ -155,5 +161,15 @@ def format_headers(headers)
155161
acc
156162
end
157163
end
164+
165+
def request_default_port?(req)
166+
[["http", 80], ["https", 443]].include?([req.scheme, req.port])
167+
end
168+
169+
def rewrite_uri(uri, original_req)
170+
uri.scheme = original_req.scheme
171+
uri.host = original_req.host
172+
uri.port = original_req.port unless request_default_port?(original_req)
173+
end
158174
end
159175
end

spec/rack/reverse_proxy_spec.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,16 @@ def app
255255
get "http://example.com:3000/test/stuff"
256256
expect(last_response.headers["location"]).to eq("http://example.com:3000/bar")
257257
end
258+
259+
it "doesn't keep the port when it's default for the protocol" do
260+
# webmock doesn't allow to stub an https URI, but this is enough to
261+
# reply to the https code path
262+
stub_request(:get, "http://example.com/test/stuff").to_return(
263+
:headers => { "location" => "http://test.com/bar" }
264+
)
265+
get "https://example.com/test/stuff"
266+
expect(last_response.headers["location"]).to eq("https://example.com/bar")
267+
end
258268
end
259269

260270
describe "with ambiguous routes and all matching" do
@@ -288,6 +298,27 @@ def app
288298
end
289299
end
290300

301+
describe "with force ssl turned on" do
302+
def app
303+
Rack::ReverseProxy.new(dummy_app) do
304+
reverse_proxy "/test", "http://example1.com/",
305+
:force_ssl => true, :replace_response_host => true
306+
end
307+
end
308+
309+
it "redirects to the ssl version when requesting non-ssl" do
310+
stub_request(:get, "http://example1.com/test/stuff").to_return(:body => "proxied")
311+
get "http://example.com/test/stuff"
312+
expect(last_response.headers["Location"]).to eq("https://example.com/test/stuff")
313+
end
314+
315+
it "does nothing when already ssl" do
316+
stub_request(:get, "http://example1.com/test/stuff").to_return(:body => "proxied")
317+
get "https://example.com/test/stuff"
318+
expect(last_response.body).to eq("proxied")
319+
end
320+
end
321+
291322
describe "with a route as a regular expression" do
292323
def app
293324
Rack::ReverseProxy.new(dummy_app) do

0 commit comments

Comments
 (0)