Skip to content

Commit 62a10fa

Browse files
committed
Extracted Rule::Matchers
1 parent 9b47bae commit 62a10fa

File tree

2 files changed

+99
-31
lines changed

2 files changed

+99
-31
lines changed

lib/rack_reverse_proxy/middleware.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,12 @@ def call(env)
5050
private
5151

5252
def proxy(env, source_request, rule)
53-
uri = rule.get_uri(source_request.fullpath, env)
53+
uri = rule.get_uri(
54+
source_request.fullpath,
55+
env,
56+
Rack::Proxy.extract_http_request_headers(source_request.env),
57+
source_request
58+
)
5459
return @app.call(env) if uri.nil?
5560

5661
options = @global_options.dup.merge(rule.options)

lib/rack_reverse_proxy/rule.rb

Lines changed: 93 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,44 @@ class Rule
55
attr_reader :options
66

77
def initialize(spec, url = nil, options = {})
8-
@custom_url = url.nil?
8+
@has_custom_url = url.nil?
99
@url = url
1010
@options = options
1111
@spec = build_matcher(spec)
1212
end
1313

1414
def proxy?(path, *args)
15-
_matches(path, *args).count > 0
15+
matches(path, *args).any?
1616
end
1717

18-
def get_uri(path, env)
19-
Candidate.new(self, url, custom_url, path, env).build_uri
18+
def get_uri(path, env, *args)
19+
Candidate.new(
20+
self,
21+
has_custom_url,
22+
path,
23+
env,
24+
matches(path, *args)
25+
).build_uri
2026
end
2127

2228
def to_s
2329
%("#{spec}" => "#{url}")
2430
end
2531

26-
# @private
27-
def _matches(path, *args)
28-
headers = args[0]
29-
rackreq = args[1]
30-
arity = spec.method(:match).arity
31-
if arity == -1
32-
match = spec.match(path)
33-
else
34-
params = [path, (@options[:accept_headers] ? headers : nil), rackreq]
35-
match = spec.match(*params[0..(arity - 1)])
36-
end
37-
# FIXME: This state mutation is very confusing
38-
@url = match.url(path) if match && custom_url
39-
Array(match)
40-
end
41-
4232
private
4333

44-
attr_reader :spec, :url, :custom_url
34+
attr_reader :spec, :url, :has_custom_url
35+
36+
def matches(path, *args)
37+
Matches.new(
38+
spec,
39+
url,
40+
path,
41+
options[:accept_headers],
42+
has_custom_url,
43+
*args
44+
)
45+
end
4546

4647
def build_matcher(spec)
4748
return /^#{spec}/ if spec.is_a?(String)
@@ -51,13 +52,14 @@ def build_matcher(spec)
5152

5253
# Candidate represents a request being matched
5354
class Candidate
54-
def initialize(rule, url, custom_url, path, env)
55+
def initialize(rule, has_custom_url, path, env, matches)
5556
@rule = rule
5657
@env = env
5758
@path = path
58-
@custom_url = custom_url
59+
@has_custom_url = has_custom_url
60+
@matches = matches
5961

60-
@url = evaluate(url)
62+
@url = evaluate(matches.custom_url)
6163
end
6264

6365
def build_uri
@@ -67,11 +69,11 @@ def build_uri
6769

6870
private
6971

70-
attr_reader :rule, :url, :custom_url, :path, :env
72+
attr_reader :rule, :url, :has_custom_url, :path, :env, :matches
7173

7274
def raw_uri
7375
return substitute_matches if with_substitutions?
74-
return just_uri if custom_url
76+
return just_uri if has_custom_url
7577
uri_with_path
7678
end
7779

@@ -98,13 +100,74 @@ def with_substitutions?
98100
end
99101

100102
def substitute_matches
101-
matches.each_with_index.inject(url) do |url, (match, i)|
102-
url.gsub("$#{i}", match)
103+
matches.substitute(url)
104+
end
105+
end
106+
107+
# Matches represents collection of matched objects for Rule
108+
class Matches
109+
# FIXME: eliminate :url, :accept_headers, :has_custom_url
110+
def initialize(spec, url, path, accept_headers, has_custom_url, headers, rackreq, *_)
111+
@spec = spec
112+
@url = url
113+
@path = path
114+
@has_custom_url = has_custom_url
115+
@rackreq = rackreq
116+
117+
@headers = headers if accept_headers
118+
@spec_arity = spec.method(:match).arity
119+
end
120+
121+
def any?
122+
found.any?
123+
end
124+
125+
def custom_url
126+
return url unless has_custom_url
127+
found.map do |match|
128+
match.url(path)
129+
end.first
130+
end
131+
132+
def substitute(url)
133+
found.each_with_index.inject(url) do |acc, (match, i)|
134+
acc.gsub("$#{i}", match)
103135
end
104136
end
105137

106-
def matches
107-
rule._matches(path)
138+
private
139+
140+
attr_reader :spec, :url, :path, :headers, :rackreq, :spec_arity, :has_custom_url
141+
142+
def found
143+
@_found ||= find_matches
144+
end
145+
146+
def find_matches
147+
Array(
148+
spec.match(*spec_params)
149+
)
150+
end
151+
152+
def spec_params
153+
@_spec_params ||= _spec_params
154+
end
155+
156+
def _spec_params
157+
[
158+
path,
159+
headers,
160+
rackreq
161+
][0...spec_param_count]
162+
end
163+
164+
def spec_param_count
165+
@_spec_param_count ||= _spec_param_count
166+
end
167+
168+
def _spec_param_count
169+
return 1 if spec_arity == -1
170+
spec_arity
108171
end
109172
end
110173
end

0 commit comments

Comments
 (0)