Class: OpenapiFirst::Router

Inherits:
Object
  • Object
show all
Defined in:
lib/openapi_first/router.rb,
lib/openapi_first/router/find_content.rb,
lib/openapi_first/router/find_response.rb,
lib/openapi_first/router/path_template.rb

Overview

Router can map requests / responses to their API definition

Constant Summary collapse

RequestMatch =

Returned by #match

Data.define(:request_definition, :params, :error, :responses) do
  def match_response(status:, content_type:)
    FindResponse.call(responses, status, content_type, request_method: request_definition.request_method,
                                                       path: request_definition.path)
  end
end
Route =

Returned by #routes to introspect all routes

Data.define(:path, :request_method, :requests, :responses)

Instance Method Summary collapse

Constructor Details

#initializeRouter

Returns a new instance of Router.



24
25
26
27
# File 'lib/openapi_first/router.rb', line 24

def initialize
  @static = {}
  @dynamic = {} # TODO: use a trie or similar
end

Instance Method Details

#add_request(request, request_method:, path:, content_type: nil) ⇒ Object

Add a request definition



42
43
44
# File 'lib/openapi_first/router.rb', line 42

def add_request(request, request_method:, path:, content_type: nil)
  route_at(path, request_method)[:requests][content_type] = request
end

#add_response(response, request_method:, path:, status:, response_content_type: nil) ⇒ Object

Add a response definition



47
48
49
# File 'lib/openapi_first/router.rb', line 47

def add_response(response, request_method:, path:, status:, response_content_type: nil)
  (route_at(path, request_method)[:responses][status] ||= {})[response_content_type] = response
end

#match(request_method, path, content_type: nil) ⇒ Object

Return all request objects that match the given path and request method



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/openapi_first/router.rb', line 52

def match(request_method, path, content_type: nil)
  path_item, params = find_path_item(path)
  return NOT_FOUND unless path_item

  contents = path_item.dig(request_method, :requests)
  return NOT_FOUND.with(error: Failure.new(:method_not_allowed)) unless contents

  request_definition = FindContent.call(contents, content_type)
  unless request_definition
    message = "#{content_type_err(content_type)} Content-Type should be #{contents.keys.join(' or ')}."
    return NOT_FOUND.with(error: Failure.new(:unsupported_media_type, message:))
  end

  responses = path_item.dig(request_method, :responses)
  RequestMatch.new(request_definition:, params:, error: nil, responses:)
end

#routesObject

Returns an enumerator of all routes



30
31
32
33
34
35
36
37
38
39
# File 'lib/openapi_first/router.rb', line 30

def routes
  @static.chain(@dynamic).lazy.flat_map do |path, request_methods|
    request_methods.filter_map do |request_method, content|
      next if request_method == :template

      Route.new(path:, request_method:, requests: content[:requests].each_value,
                responses: content[:responses].each_value.lazy.flat_map(&:values))
    end
  end
end