diff --git a/lib/hoodwink/request.rb b/lib/hoodwink/request.rb index 2ff5708..3028342 100644 --- a/lib/hoodwink/request.rb +++ b/lib/hoodwink/request.rb @@ -3,12 +3,11 @@ class Request attr_reader :raw_request attr_reader :resource_path - def initialize(raw_request, resource_path) + def initialize(raw_request, resource_path_re) @raw_request = raw_request - @resource_path = resource_path - @collection_re = %r{^#{resource_path}(\.(?.*))?$} - @resource_re = %r{^#{resource_path}/(?[^.]+)(.(?.*))?$} + @collection_re = %r{^#{resource_path_re}(\.(?.*))?$} + @resource_re = %r{^#{resource_path_re}/(?[^.]+)(.(?.*))?$} end def path diff --git a/lib/hoodwink/request_interceptor.rb b/lib/hoodwink/request_interceptor.rb index 6837e0f..c876638 100644 --- a/lib/hoodwink/request_interceptor.rb +++ b/lib/hoodwink/request_interceptor.rb @@ -44,36 +44,45 @@ def mock_resource(resource_url, resource_name=nil, &block_extension) end end + # take any segments out of the path + segments = resource_uri.path.scan(%r{(?!/)[^/]+}) + segment_res = segments.map do |s| + if s.match(/:(?.+)/) + "(?<#{$~[:var]}>[^/]+)" + else + s + end + end + resource_path_re = "/" + segment_res.join("/") + # create a resource responder - responder = ResourceResponder.new(resource_uri.path, resource_name.singularize, datastore, datastore_proxy_class) + responder = ResourceResponder.new(resource_path_re, resource_name.singularize, datastore, datastore_proxy_class) # store the responder responders[resource_url] = responder # wire requests to the responder - SUPPORTED_FORMATS.each do |mimetype, format| - stub_request_for(responder, resource_uri, "*/*", ".#{format}") - stub_request_for(responder, resource_uri, mimetype, ".#{format}") - stub_request_for(responder, resource_uri, mimetype, "") + SUPPORTED_FORMATS.each do |mimetype, extension| + stub_request_for(responder, resource_uri, resource_path_re, "*/*", ".#{extension}") + stub_request_for(responder, resource_uri, resource_path_re, mimetype, ".#{extension}") + stub_request_for(responder, resource_uri, resource_path_re, mimetype, "") end end private - def stub_request_for(responder, resource_uri, mimetype, extension) - resource_path = resource_uri.path + def stub_request_for(responder, resource_uri, resource_path_re, mimetype, extension) resource_host = resource_uri.host - resource_port = resource_uri.port.nil? ? "": ":#{resource_uri.port}" + resource_port = [nil, 80].include?(resource_uri.port) ? "": ":#{resource_uri.port}" # TODO: add tests for username/password # TODO: add tests for port # TODO: add tests for port :80 same as nil - collection_re = %r{^https?://(.*@)?#{resource_host}#{resource_port}#{resource_path}#{extension}(\?(?.*))?$} - resource_re = %r{^https?://(.*@)?#{resource_host}#{resource_port}#{resource_path}/([^./]+)#{extension}(\?(?.*))?$} - - content_type_hash = mimetype.empty? + collection_re = %r{^https?://(.*@)?#{resource_host}#{resource_port}#{resource_path_re}#{extension}(\?(?.*))?$} + resource_re = %r{^https?://(.*@)?#{resource_host}#{resource_port}#{resource_path_re}/([^./]+)#{extension}(\?(?.*))?$} - response = Proc.new do |request| + response = Proc.new do |raw_request| + request = Request.new(raw_request, resource_path_re) responder.response_for(request)#.tap {|r| pp r} end diff --git a/lib/hoodwink/resource_responder.rb b/lib/hoodwink/resource_responder.rb index ebdfe63..c777304 100644 --- a/lib/hoodwink/resource_responder.rb +++ b/lib/hoodwink/resource_responder.rb @@ -22,8 +22,7 @@ def format_as(format, root, data) # GET "/fish/1.json", {}, @fish # PUT "/fish/1.json", {}, nil, 204 # DELETE "/fish/1.json", {}, nil, 200 - def response_for(raw_request) - request = Request.new(raw_request, resource_path) + def response_for(request) datastore_proxy = datastore_proxy_class.new(@resource_name, datastore, request) case [request.request_type, request.method] @@ -34,7 +33,7 @@ def response_for(raw_request) response_body = format_as(response_format, @resource_name.singularize, datastore_proxy.find_all) response_for_get(response_body, response_format) - # TODO: rename data + # TODO: resource_location generation for segmented routes when [:collection, :post] posted_resource = request.resource # create(resource_name, hash) @@ -44,7 +43,6 @@ def response_for(raw_request) response_body = format_as(response_format, @resource_name.singularize, new_resource) response_for_nonget(request, resource_location, response_body) - # TODO: rename data when [:resource, :get] resource = datastore_proxy.find(request.resource_id) response_body = format_as(request.response_format, @resource_name.singularize, resource) @@ -66,7 +64,7 @@ def response_for(raw_request) response_for_nonget(request, resource_location, nil) else - raise UnableToHandleRequest, "Could not handle request for #{request.method} on #{path}" + raise UnableToHandleRequest, "Could not handle request for #{request.method} on #{request.path}" end rescue RecordNotFound diff --git a/spec/lib/hoodwink/request_interceptor_spec.rb b/spec/lib/hoodwink/request_interceptor_spec.rb index 38ed6cb..617bc6b 100644 --- a/spec/lib/hoodwink/request_interceptor_spec.rb +++ b/spec/lib/hoodwink/request_interceptor_spec.rb @@ -6,7 +6,6 @@ subject { Hoodwink::RequestInterceptor.instance } let(:http) { Net::HTTP.new("localhost.localdomain") } - let(:responder) { subject.responders[fish_endpoint] } let(:fish_endpoint) { "http://localhost.localdomain/fish" } let(:fowl_endpoint) { "http://localhost.localdomain/fowl" } @@ -54,19 +53,19 @@ end describe "#mock_resource without extensions" do - context "a normal endpoint" do + context "a normal endpoint" do before { subject.mock_resource fish_endpoint } - let (:resource_path) { "/fish" } - + let(:resource_path) { "/fish" } + let(:responder) { subject.responders[fish_endpoint] } include_examples "for a mocked resource" end - # context "a segmented endpoint" do - # before { subject.mock_resource segmented_endpoint } - # let (:resource_path) { "/cats/25/dogs/34/fleas" } - - # include_examples "for a mocked resource" - # end + context "a segmented endpoint" do + before { subject.mock_resource segmented_endpoint } + let(:resource_path) { "/cats/25/dogs/34/fleas" } + let(:responder) { subject.responders[segmented_endpoint] } + include_examples "for a mocked resource" + end end describe "#mock_resource with extensions" do @@ -78,7 +77,8 @@ def find_all ; raise ExpectedToRaise ; end end end - let (:resource_path) { "/fish" } + let(:resource_path) { "/fish" } + let(:responder) { subject.responders[fish_endpoint] } include_examples "for a mocked resource" end diff --git a/spec/lib/hoodwink/resource_responder_spec.rb b/spec/lib/hoodwink/resource_responder_spec.rb index c7b9890..ed1af1b 100644 --- a/spec/lib/hoodwink/resource_responder_spec.rb +++ b/spec/lib/hoodwink/resource_responder_spec.rb @@ -36,7 +36,7 @@ describe "#response_for" do before(:all) { RawRequest = Struct.new("Request", :method, :uri, :body, :headers) } - let(:response) { subject.response_for(request) } + let(:response) { subject.response_for(Hoodwink::Request.new(request, "/fowl")) } # accept/ # method resource extension content-type ==> code content-type location