Skip to content

Commit 4a1d99a

Browse files
committed
refactor request so routing_tokens are immutable and passed to constructor
as suggested by @bethesque at https://github.com/seancribbs/webmachine-ruby/pull/223/files#r25999998
1 parent 7f7b546 commit 4a1d99a

File tree

4 files changed

+32
-34
lines changed

4 files changed

+32
-34
lines changed

lib/webmachine/adapters/rack.rb

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,13 @@ def build_webmachine_request(rack_req, headers)
9797
Webmachine::Request.new(rack_req.request_method,
9898
rack_req.url,
9999
headers,
100-
RequestBody.new(rack_req))
100+
RequestBody.new(rack_req),
101+
routing_tokens(rack_req)
102+
)
103+
end
104+
105+
def routing_tokens(rack_req)
106+
nil # no-op for default, un-mapped rack adapter
101107
end
102108

103109
class RackResponse
@@ -173,13 +179,10 @@ def each
173179
end # class Rack
174180

175181
class RackMapped < Rack
176-
def build_webmachine_request(rack_req, headers)
177-
request = super
182+
def routing_tokens(rack_req)
178183
routing_match = rack_req.path_info.match(Webmachine::Request::ROUTING_PATH_MATCH)
179184
routing_path = routing_match ? routing_match[1] : ""
180-
routing_tokens = routing_path.split(SLASH)
181-
request.routing_tokens = routing_tokens
182-
request
185+
routing_path.split(SLASH)
183186
end
184187
end
185188

lib/webmachine/request.rb

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@ class Request
1111

1212
extend Forwardable
1313

14-
attr_reader :method, :uri, :headers, :body
14+
attr_reader :method, :uri, :headers, :body, :routing_tokens
1515
attr_accessor :disp_path, :path_info, :path_tokens
16-
attr_writer :routing_tokens
1716

1817
# @param [String] method the HTTP request method
1918
# @param [URI] uri the requested URI, including host, scheme and
2019
# port
2120
# @param [Headers] headers the HTTP request headers
2221
# @param [String,#to_s,#each,nil] body the entity included in the
2322
# request, if present
24-
def initialize(method, uri, headers, body)
23+
def initialize(method, uri, headers, body, routing_tokens=nil)
2524
@method, @headers, @body = method, headers, body
2625
@uri = build_uri(uri, headers)
26+
@routing_tokens = routing_tokens || @uri.path.match(ROUTING_PATH_MATCH)[1].split(SLASH)
2727
end
2828

2929
def_delegators :headers, :[]
@@ -167,10 +167,6 @@ def options?
167167

168168
ROUTING_PATH_MATCH = /^\/(.*)/.freeze
169169

170-
def routing_tokens
171-
@routing_tokens ||= uri.path.match(ROUTING_PATH_MATCH)[1].split(SLASH)
172-
end
173-
174170
private
175171

176172
IPV6_MATCH = /\A\[(?<address> .* )\]:(?<port> \d+ )\z/x.freeze # string like "[::1]:80"

spec/webmachine/dispatcher/route_spec.rb

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ def warn(*msgs); end # silence warnings for tests
77
describe Webmachine::Dispatcher::Route do
88
let(:method) { "GET" }
99
let(:uri) { URI.parse("http://localhost:8080/") }
10-
let(:request){ Webmachine::Request.new(method, uri, Webmachine::Headers.new, "") }
10+
let(:routing_tokens) { nil }
11+
let(:request){ Webmachine::Request.new(method, uri, Webmachine::Headers.new, "", routing_tokens) }
1112
let(:resource){ Class.new(Webmachine::Resource) }
1213

1314
describe '#apply' do
@@ -16,9 +17,7 @@ def warn(*msgs); end # silence warnings for tests
1617
}
1718

1819
describe 'a path_info fragment' do
19-
before do
20-
uri.path = '/hello/planet%20earth%20++'
21-
end
20+
let(:uri) { URI.parse("http://localhost:8080/hello/planet%20earth%20++") }
2221

2322
it 'should decode the value' do
2423
route.apply(request)
@@ -30,14 +29,10 @@ def warn(*msgs); end # silence warnings for tests
3029
matcher :match_route do |*expected|
3130
route = Webmachine::Dispatcher::Route.new(expected[0], Class.new(Webmachine::Resource), expected[1] || {})
3231
match do |actual|
33-
case actual
34-
when String
35-
request.uri.path = actual if String === actual
36-
when Array
37-
request.uri.path = "/some/route/" + actual.join("/")
38-
request.routing_tokens = actual
39-
end
40-
route.match?(request)
32+
uri = URI.parse("http://localhost:8080")
33+
uri.path = actual
34+
req = Webmachine::Request.new("GET", uri, Webmachine::Headers.new, "", routing_tokens)
35+
route.match?(req)
4136
end
4237

4338
failure_message do |_|
@@ -132,7 +127,8 @@ def call(request)
132127
end
133128

134129
context "with a request with explicitly specified routing tokens" do
135-
subject { ["foo", "bar"] }
130+
subject { "/some/route/foo/bar" }
131+
let(:routing_tokens) { ["foo", "bar"] }
136132
it { is_expected.to match_route(["foo", "bar"]) }
137133
it { is_expected.to match_route(["foo", :id]) }
138134
it { is_expected.to match_route ['*'] }
@@ -187,7 +183,8 @@ def call(request)
187183

188184
context "on a deep path" do
189185
subject { described_class.new(%w{foo bar baz}, resource) }
190-
before { request.uri.path = "/foo/bar/baz"; subject.apply(request) }
186+
let(:uri) { URI.parse("http://localhost:8080/foo/bar/baz") }
187+
before { subject.apply(request) }
191188

192189
it "should assign the dispatched path as the path past the initial slash" do
193190
expect(request.disp_path).to eq("foo/bar/baz")

spec/webmachine/request_spec.rb

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
describe Webmachine::Request do
44
subject { request }
55

6-
let(:uri) { URI.parse("http://localhost:8080/some/resource") }
7-
let(:http_method) { "GET" }
8-
let(:headers) { Webmachine::Headers.new }
9-
let(:body) { "" }
10-
let(:request) { Webmachine::Request.new(http_method, uri, headers, body) }
6+
let(:uri) { URI.parse("http://localhost:8080/some/resource") }
7+
let(:http_method) { "GET" }
8+
let(:headers) { Webmachine::Headers.new }
9+
let(:body) { "" }
10+
let(:routing_tokens) { nil }
11+
let(:request) { Webmachine::Request.new(http_method, uri, headers, body, routing_tokens) }
1112

1213
it "should provide access to the headers via brackets" do
1314
subject.headers['Accept'] = "*/*"
@@ -242,14 +243,15 @@ def body; block_given? ? yield(@body) : @body; end
242243
describe '#routing_tokens' do
243244
subject { request.routing_tokens }
244245

245-
context "haven't be explicitly set" do
246+
context "haven't been explicitly set" do
247+
let(:routing_tokens) { nil }
246248
it "extracts the routing tokens from the path portion of the uri" do
247249
expect(subject).to eq(["some", "resource"])
248250
end
249251
end
250252

251253
context "have been explicitly set" do
252-
before { request.routing_tokens = ["foo", "bar"] }
254+
let(:routing_tokens) { ["foo", "bar"] }
253255

254256
it "uses the specified routing_tokens" do
255257
expect(subject).to eq(["foo", "bar"])

0 commit comments

Comments
 (0)