diff --git a/lib/rack_reverse_proxy/rule.rb b/lib/rack_reverse_proxy/rule.rb index 0635482..34b0bd2 100644 --- a/lib/rack_reverse_proxy/rule.rb +++ b/lib/rack_reverse_proxy/rule.rb @@ -48,7 +48,7 @@ def matches(path, *args) spec, url, path, - options[:accept_headers], + options, has_custom_url, *args ) @@ -124,14 +124,15 @@ class Matches # rubocop:disable Metrics/ParameterLists # FIXME: eliminate :url, :accept_headers, :has_custom_url - def initialize(spec, url, path, accept_headers, has_custom_url, headers, rackreq, *_) + def initialize(spec, url, path, options, has_custom_url, headers, rackreq, *_) @spec = spec @url = url @path = path @has_custom_url = has_custom_url @rackreq = rackreq - @headers = headers if accept_headers + @headers = headers if options[:accept_headers] + @constraint = options[:constraint] @spec_arity = spec.method(spec_match_method_name).arity end @@ -164,7 +165,7 @@ def transform(response, request_uri) private - attr_reader :spec, :url, :path, :headers, :rackreq, :spec_arity, :has_custom_url + attr_reader :spec, :url, :path, :headers, :rackreq, :spec_arity, :has_custom_url, :constraint def found @_found ||= find_matches @@ -172,7 +173,7 @@ def found def find_matches Array( - spec.send(spec_match_method_name, *spec_params) + spec.send(spec_match_method_name, *spec_params) && apply_constraints! ) end @@ -201,6 +202,14 @@ def spec_match_method_name return :match if spec.respond_to?(:match) :call end + + def apply_constraints! + if constraint.blank? + return true + end + + constraint.call(rackreq) + end end end end diff --git a/spec/rack/reverse_proxy_spec.rb b/spec/rack/reverse_proxy_spec.rb index 4f4cfbb..12578de 100644 --- a/spec/rack/reverse_proxy_spec.rb +++ b/spec/rack/reverse_proxy_spec.rb @@ -440,6 +440,26 @@ def app end end + describe "with a matching constraint" do + def app + Rack::ReverseProxy.new(dummy_app) do + reverse_proxy "/test", "http://example1.com/", constraint: ->() { true } + reverse_proxy "/test2", "http://example2.com/", constraint: ->() { false } + end + end + + it "is considered when the route matches" do + stub_request(:get, "http://example1.com/test").to_return(:body => "Proxied App") + get "/test" + expect(last_response.body).to eq("Proxied App") + end + + it "forwards requests to the calling app when path matches but constraint returns false" do + get "/test2" + expect(last_response.body).to eq("Dummy App") + end + end + describe "with force ssl turned on" do def app Rack::ReverseProxy.new(dummy_app) do