diff --git a/lib/openapi_first/router.rb b/lib/openapi_first/router.rb index 9f04ec8a..d94e9ff7 100644 --- a/lib/openapi_first/router.rb +++ b/lib/openapi_first/router.rb @@ -97,10 +97,15 @@ def find_path_item(request_path) found = @static[request_path] return [found, {}] if found - @dynamic.find do |_path, path_item| + matches = @dynamic.filter_map do |_path, path_item| params = path_item[:template].match(request_path) - return [path_item, params] if params + next unless params + + [path_item, params, params.values.sum(&:length)] end + + matches&.min_by { |_path_item, _params, length| length } + &.then { |path_item, params, _length| [path_item, params] } end end end diff --git a/spec/router_spec.rb b/spec/router_spec.rb index 4ebd5c4f..5e719d29 100644 --- a/spec/router_spec.rb +++ b/spec/router_spec.rb @@ -8,7 +8,8 @@ [ double(path: '/{id}', request_method: 'get'), double(path: '/{id}', request_method: 'patch'), - double(path: '/a', request_method: 'get') + double(path: '/a', request_method: 'get'), + double(path: '/a{format}', request_method: 'get') ] end @@ -30,6 +31,12 @@ expect(router.match('GET', '/c/d').error).to have_attributes(type: :not_found) end + it 'returns a match with only a request method' do + match = router.match('GET', '/a.json') + expect(match.request_definition.path).to eq('/a.{format}') + expect(match.request_definition).to be(requests[3]) + end + it 'returns an incomplete match for unknown request method' do expect(router.match('DELETE', '/b').error).to have_attributes(type: :method_not_allowed) end