Skip to content

Commit 7f7b546

Browse files
committed
add RackMapped adapter that correctly handles routing when hosted from a rack mapped URI
`Webmachine::Adapters::RackMapped` is implemented as a subclass of `Webmachine::Adapters::Rack`, and simply overrides the way the `Webmachine::Request` is built to explicitly set the `routing_tokens` from the rack request `PATH_INFO` string - rather than from the full uri path string as the base rack adapter does. Rack provides the path that the app should use in the `PATH_INFO` env var. This is the correct value to use for routing etc to work with mapped apps. Note, this was done as a separate class as suggested by @bethesque to preserve backward compatibility. If any webmachine apps are running as mapped rack apps already, they may have gotten around not being able to host the app on a mapped path by specifying the full URI path in the routing config - which would no longer work if this change was made on the base rack adapter.
1 parent 7e9cd6a commit 7f7b546

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

lib/webmachine/adapters/rack.rb

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,7 @@ def call(env)
5959
headers = Webmachine::Headers.from_cgi(env)
6060

6161
rack_req = ::Rack::Request.new env
62-
request = Webmachine::Request.new(rack_req.request_method,
63-
rack_req.url,
64-
headers,
65-
RequestBody.new(rack_req))
62+
request = build_webmachine_request(rack_req, headers)
6663

6764
response = Webmachine::Response.new
6865
application.dispatcher.dispatch(request, response)
@@ -95,6 +92,14 @@ def call(env)
9592
rack_res.finish
9693
end
9794

95+
private
96+
def build_webmachine_request(rack_req, headers)
97+
Webmachine::Request.new(rack_req.request_method,
98+
rack_req.url,
99+
headers,
100+
RequestBody.new(rack_req))
101+
end
102+
98103
class RackResponse
99104
ONE_FIVE = '1.5'.freeze
100105

@@ -167,5 +172,16 @@ def each
167172
end # class RequestBody
168173
end # class Rack
169174

175+
class RackMapped < Rack
176+
def build_webmachine_request(rack_req, headers)
177+
request = super
178+
routing_match = rack_req.path_info.match(Webmachine::Request::ROUTING_PATH_MATCH)
179+
routing_path = routing_match ? routing_match[1] : ""
180+
routing_tokens = routing_path.split(SLASH)
181+
request.routing_tokens = routing_tokens
182+
request
183+
end
184+
end
185+
170186
end # module Adapters
171187
end # module Webmachine

spec/webmachine/adapters/rack_spec.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414
end
1515
end
1616

17+
describe Webmachine::Adapters::RackMapped do
18+
it_should_behave_like :adapter_lint do
19+
it "should set Server header" do
20+
response = client.request(Net::HTTP::Get.new("/test"))
21+
expect(response["Server"]).to match(/Webmachine/)
22+
expect(response["Server"]).to match(/Rack/)
23+
end
24+
end
25+
end
26+
1727
describe Webmachine::Adapters::Rack::RackResponse do
1828
context "on Rack < 1.5 release" do
1929
before { allow(Rack).to receive_messages(:release => "1.4") }
@@ -55,3 +65,27 @@
5565
end
5666
end
5767
end
68+
69+
describe Webmachine::Adapters::RackMapped do
70+
let(:app) do
71+
Rack::Builder.new do
72+
map '/some/route' do
73+
run(Webmachine::Application.new do |app|
74+
app.add_route(["test"], Test::Resource)
75+
app.configure do | config |
76+
config.adapter = :RackMapped
77+
end
78+
end.adapter)
79+
end
80+
end
81+
end
82+
83+
context "using Rack::Test" do
84+
include Rack::Test::Methods
85+
86+
it "provides the full request URI" do
87+
rack_response = get "some/route/test", nil, {"HTTP_ACCEPT" => "test/response.request_uri"}
88+
expect(rack_response.body).to eq "http://example.org/some/route/test"
89+
end
90+
end
91+
end

0 commit comments

Comments
 (0)