Skip to content

Commit

Permalink
Matching on segmented urls works
Browse files Browse the repository at this point in the history
  • Loading branch information
ijcd committed Mar 1, 2012
1 parent 2f41b0e commit d8862dd
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 34 deletions.
7 changes: 3 additions & 4 deletions lib/hoodwink/request.rb
Expand Up @@ -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}(\.(?<url_format>.*))?$}
@resource_re = %r{^#{resource_path}/(?<id>[^.]+)(.(?<url_format>.*))?$}
@collection_re = %r{^#{resource_path_re}(\.(?<url_format>.*))?$}
@resource_re = %r{^#{resource_path_re}/(?<id>[^.]+)(.(?<url_format>.*))?$}
end

def path
Expand Down
35 changes: 22 additions & 13 deletions lib/hoodwink/request_interceptor.rb
Expand Up @@ -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>.+)/)
"(?<#{$~[: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}(\?(?<params>.*))?$}
resource_re = %r{^https?://(.*@)?#{resource_host}#{resource_port}#{resource_path}/([^./]+)#{extension}(\?(?<params>.*))?$}

content_type_hash = mimetype.empty?
collection_re = %r{^https?://(.*@)?#{resource_host}#{resource_port}#{resource_path_re}#{extension}(\?(?<params>.*))?$}
resource_re = %r{^https?://(.*@)?#{resource_host}#{resource_port}#{resource_path_re}/([^./]+)#{extension}(\?(?<params>.*))?$}

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

Expand Down
8 changes: 3 additions & 5 deletions lib/hoodwink/resource_responder.rb
Expand Up @@ -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]
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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
Expand Down
22 changes: 11 additions & 11 deletions spec/lib/hoodwink/request_interceptor_spec.rb
Expand Up @@ -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" }
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down
2 changes: 1 addition & 1 deletion spec/lib/hoodwink/resource_responder_spec.rb
Expand Up @@ -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
Expand Down

0 comments on commit d8862dd

Please sign in to comment.