Class: OpenapiFirst::Definition

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/openapi_first/definition.rb

Overview

Represents an OpenAPI API Description document This is returned by OpenapiFirst.load.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(contents, filepath = nil) {|@config| ... } ⇒ Definition

Returns a new instance of Definition.

Yields:



23
24
25
26
27
28
29
30
31
# File 'lib/openapi_first/definition.rb', line 23

def initialize(contents, filepath = nil)
  @filepath = filepath
  @config = OpenapiFirst.configuration.child
  yield @config if block_given?
  @config.freeze
  @router = Builder.build_router(contents, filepath:, config:)
  @resolved = contents
  @paths = @router.routes.map(&:path).to_a.uniq # TODO: Refactor
end

Instance Attribute Details

#configConfiguration (readonly)



15
16
17
# File 'lib/openapi_first/definition.rb', line 15

def config
  @config
end

#filepathString? (readonly)



13
14
15
# File 'lib/openapi_first/definition.rb', line 13

def filepath
  @filepath
end

#pathsEnumerable[String] (readonly)



17
18
19
# File 'lib/openapi_first/definition.rb', line 17

def paths
  @paths
end

#routerRouter (readonly)



19
20
21
# File 'lib/openapi_first/definition.rb', line 19

def router
  @router
end

Instance Method Details

#[](key) ⇒ Hash

Gives access to the raw resolved Hash. Like ‘mydefinition.dig(’schemas’, ‘Stations’)‘



36
# File 'lib/openapi_first/definition.rb', line 36

def_delegators :@resolved, :[]

#inspectObject



61
62
63
# File 'lib/openapi_first/definition.rb', line 61

def inspect
  "#<#{self.class.name} @key='#{key}'>"
end

#keyString

Returns a unique identifier for this API definition



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/openapi_first/definition.rb', line 45

def key
  return filepath if filepath

  info = self['info'] || {}
  title = info['title']
  version = info['version']

  if title.nil? || version.nil?
    raise ArgumentError,
          "Cannot generate key for the OpenAPI document because 'info.title' or 'info.version' is missing. " \
          'Please add these fields to your OpenAPI document.'
  end

  "#{title} @ #{version}"
end

#routesEnumerable[Router::Route]

Returns an Enumerable of available Routes for this API description.



41
# File 'lib/openapi_first/definition.rb', line 41

def_delegators :@router, :routes

#validate_request(request, raise_error: false) ⇒ ValidatedRequest

Validates the request against the API description.



69
70
71
72
73
74
75
76
77
78
79
# File 'lib/openapi_first/definition.rb', line 69

def validate_request(request, raise_error: false)
  route = @router.match(request.request_method, resolve_path(request), content_type: request.content_type)
  if route.error
    ValidatedRequest.new(request, error: route.error)
  else
    route.request_definition.validate(request, route_params: route.params)
  end.tap do |validated|
    @config.after_request_validation.each { |hook| hook.call(validated, self) }
    raise validated.error.exception(validated) if validated.error && raise_error
  end
end

#validate_response(rack_request, rack_response, raise_error: false) ⇒ ValidatedResponse

Validates the response against the API description.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/openapi_first/definition.rb', line 86

def validate_response(rack_request, rack_response, raise_error: false)
  route = @router.match(rack_request.request_method, resolve_path(rack_request),
                        content_type: rack_request.content_type)
  return if route.error # Skip response validation for unknown requests

  response_match = route.match_response(status: rack_response.status, content_type: rack_response.content_type)
  error = response_match.error
  validated = if error
                ValidatedResponse.new(rack_response, error:)
              else
                response_match.response.validate(rack_response)
              end
  @config.after_response_validation&.each { |hook| hook.call(validated, rack_request, self) }
  raise validated.error.exception(validated) if raise_error && validated.invalid?

  validated
end