openapi_first 0.16.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac3d5709b36ac797521a16ec11af5fe1106faf2aa2a48daf502516cc875fad47
4
- data.tar.gz: 311e4b513cb5e655397e38cadfec1eff07ae70d1136c75197f87dba8b058073c
3
+ metadata.gz: d09bae8b5126245d86fceeb81b2d0d46fb1a9e1cb10370527327edb3e370fe59
4
+ data.tar.gz: 2bd5e71bd8022506be07ab7c60b2740d490fc0f2a0995ded0f6a9c6dc4d165e3
5
5
  SHA512:
6
- metadata.gz: 85d40c11308a34a3f1a7c9886cf9826d5a36b6e9d8dc15f0a6bf9ae0d435b88f9e16576b339b0dc3b4e2a3c13bc00710fdbe6dd6bdabf1d8aa644f7f34f6cfd7
7
- data.tar.gz: ce475547d199cfabd050e4bdcbf995cecd9a72480b9bfe32e8b84e3287b4be5a95970063542522437362dd65154719c40bb3bc8449b5e4ec82a30c9bfec3f337
6
+ metadata.gz: 4d7d449f19fe40c49ea701eb28aca2a140ec41a5efb5be7433a5a60d85376a139a18c772ff34f211fbfb02e557ddddfdfad8ca547a695cb849bd62b69015775d
7
+ data.tar.gz: 6693234aab12e85893fedfa831ff21c831f00aa4040475a8a6e9fdbc5a2500e094f552ff1efef1c459af4df2eff21ad9f7ac4b6f93b2628f76d5f5169c4ad228
data/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.19.0
4
+
5
+ - Add `RackResponder`
6
+
7
+ - BREAKING CHANGE: Handler classes are now instantiated only once without any arguments and the same instance is called on each following call/request.
8
+
9
+ ## 0.18.0
10
+
11
+ Yanked. No useful changes.
12
+
13
+ ## 0.17.0
14
+
15
+ - BREAKING CHANGE: Use a Hash instead of named arguments for middleware options for better compatibility
16
+ Using named arguments is actually not supported in Rack.
17
+
18
+ ## 0.16.1
19
+
20
+ - Pin hanami-router version, because alpha6 is broken.
21
+
3
22
  ## 0.16.0
4
23
 
5
24
  - Support status code wildcards like "2XX", "4XX"
data/Gemfile.lock CHANGED
@@ -1,11 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openapi_first (0.16.0)
4
+ openapi_first (0.19.0)
5
5
  deep_merge (>= 1.2.1)
6
- hanami-router (~> 2.0.alpha5)
7
- hanami-utils (~> 2.0.alpha3)
8
- json_refs (>= 0.1.7)
6
+ hanami-router (= 2.0.alpha5)
7
+ hanami-utils (= 2.0.alpha3)
8
+ json_refs (~> 0.1, >= 0.1.7)
9
9
  json_schemer (~> 0.2.16)
10
10
  multi_json (~> 1.14)
11
11
  rack (~> 2.2)
@@ -29,33 +29,34 @@ GEM
29
29
  hanami-utils (2.0.0.alpha3)
30
30
  concurrent-ruby (~> 1.0)
31
31
  dry-transformer (~> 0.1)
32
- hansi (0.2.0)
32
+ hansi (0.2.1)
33
+ json (2.6.2)
33
34
  json_refs (0.1.7)
34
35
  hana
35
- json_schemer (0.2.19)
36
+ json_schemer (0.2.21)
36
37
  ecma-re-validator (~> 0.3)
37
38
  hana (~> 1.3)
38
39
  regexp_parser (~> 2.0)
39
40
  uri_template (~> 0.7)
40
41
  method_source (1.0.0)
41
42
  multi_json (1.15.0)
42
- mustermann (1.1.1)
43
+ mustermann (1.1.2)
43
44
  ruby2_keywords (~> 0.0.1)
44
- mustermann-contrib (1.1.1)
45
+ mustermann-contrib (1.1.2)
45
46
  hansi (~> 0.2.0)
46
- mustermann (= 1.1.1)
47
- parallel (1.21.0)
48
- parser (3.1.0.0)
47
+ mustermann (= 1.1.2)
48
+ parallel (1.22.1)
49
+ parser (3.1.2.0)
49
50
  ast (~> 2.4.1)
50
51
  pry (0.14.1)
51
52
  coderay (~> 1.1)
52
53
  method_source (~> 1.0)
53
- rack (2.2.3)
54
+ rack (2.2.4)
54
55
  rack-test (1.1.0)
55
56
  rack (>= 1.0, < 3)
56
57
  rainbow (3.1.1)
57
58
  rake (13.0.6)
58
- regexp_parser (2.2.1)
59
+ regexp_parser (2.5.0)
59
60
  rexml (3.2.5)
60
61
  rspec (3.11.0)
61
62
  rspec-core (~> 3.11.0)
@@ -66,29 +67,31 @@ GEM
66
67
  rspec-expectations (3.11.0)
67
68
  diff-lcs (>= 1.2.0, < 2.0)
68
69
  rspec-support (~> 3.11.0)
69
- rspec-mocks (3.11.0)
70
+ rspec-mocks (3.11.1)
70
71
  diff-lcs (>= 1.2.0, < 2.0)
71
72
  rspec-support (~> 3.11.0)
72
73
  rspec-support (3.11.0)
73
- rubocop (1.25.1)
74
+ rubocop (1.32.0)
75
+ json (~> 2.3)
74
76
  parallel (~> 1.10)
75
77
  parser (>= 3.1.0.0)
76
78
  rainbow (>= 2.2.2, < 4.0)
77
79
  regexp_parser (>= 1.8, < 3.0)
78
- rexml
79
- rubocop-ast (>= 1.15.1, < 2.0)
80
+ rexml (>= 3.2.5, < 4.0)
81
+ rubocop-ast (>= 1.19.1, < 2.0)
80
82
  ruby-progressbar (~> 1.7)
81
83
  unicode-display_width (>= 1.4.0, < 3.0)
82
- rubocop-ast (1.15.2)
83
- parser (>= 3.0.1.1)
84
+ rubocop-ast (1.19.1)
85
+ parser (>= 3.1.1.0)
84
86
  ruby-progressbar (1.11.0)
85
87
  ruby2_keywords (0.0.5)
86
- unicode-display_width (2.1.0)
88
+ unicode-display_width (2.2.0)
87
89
  uri_template (0.7.0)
88
90
 
89
91
  PLATFORMS
90
92
  arm64-darwin-21
91
93
  x86_64-darwin-20
94
+ x86_64-linux
92
95
 
93
96
  DEPENDENCIES
94
97
  bundler (~> 2)
data/README.md CHANGED
@@ -20,7 +20,8 @@ OpenapiFirst consists of these Rack middlewares:
20
20
 
21
21
  - [`OpenapiFirst::Router`](#OpenapiFirst::Router) – Finds the OpenAPI operation for the current request or returns 404 if no operation was found. This can be customized.
22
22
  - [`OpenapiFirst::RequestValidation`](#OpenapiFirst::RequestValidation) – Validates the request against the API description and returns 400 if the request is invalid.
23
- - [`OpenapiFirst::Responder`](#OpenapiFirst::Responder) calls the [handler](#handlers) found for the operation, sets the correct content-type and serialized the response body to json if needed.
23
+ - [`OpenapiFirst::Responder`](#OpenapiFirst::Responder) calls the [handler](#handlers) found for the operation, sets the correct content-type and serializes the response body to json if needed.
24
+ - [`OpenapiFirst::RackResponder`](#OpenapiFirst::RackResponder) calls the [handler](#handlers) found for the operation as a normal Rack application (`call(env)`) and returns the result as is.
24
25
  - [`OpenapiFirst::ResponseValidation`](#OpenapiFirst::ResponseValidation) Validates the response and raises an exception if the response body is invalid.
25
26
 
26
27
  ## OpenapiFirst::Router
@@ -121,6 +122,24 @@ run OpenapiFirst::Responder
121
122
  | `namespace:` | Optional. A class or module where to find the handler method. |
122
123
  | `resolver:` | Optional. An object that responds to `#call(operation)` and returns a [handler](#handlers). By default this is an instance of [DefaultOperationResolver](#OpenapiFirst::DefaultOperationResolver) |
123
124
 
125
+
126
+ ## OpenapiFirst::RackResponder
127
+
128
+ This Rack endpoint maps the HTTP request to a method call based on the [operationId](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#operation-object) in your API description and calls it as a normal Rack application.
129
+ It does not not serialize objects as JSON or adds a content-type.
130
+
131
+ ```ruby
132
+ run OpenapiFirst::RackResponder
133
+ ```
134
+
135
+ ### Options
136
+
137
+ | Name | Description |
138
+ | :----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
139
+ | `namespace:` | Optional. A class or module where to find the handler method. |
140
+ | `resolver:` | Optional. An object that responds to `#call(operation)` and returns a [handler](#handlers). By default this is an instance of [DefaultOperationResolver](#OpenapiFirst::DefaultOperationResolver) |
141
+
142
+
124
143
  ### OpenapiFirst::DefaultOperationResolver
125
144
 
126
145
  This is the default way to look up a handler method for an operation. Handlers are always looked up in a namespace module that needs to be specified.
@@ -129,7 +148,7 @@ It works like this:
129
148
 
130
149
  - An operationId "create_pet" or "createPet" or "create pet" calls `MyApi.create_pet(params, response)`
131
150
  - "some_things.create" calls: `MyApi::SomeThings.create(params, response)`
132
- - "pets#create" calls: `MyApi::Pets::Create.new.call(params, response)` If `MyApi::Pets::Create.new` accepts an argument, it will pass the rack `env`.
151
+ - "pets#create" instantiates the class once (`MyApi::Pets::Create.new) and calls it on every request(`instance.call(params, response)`).
133
152
 
134
153
  ### Handlers
135
154
 
data/benchmarks/Gemfile CHANGED
@@ -7,8 +7,9 @@ gem 'benchmark-memory'
7
7
  gem 'committee'
8
8
  gem 'grape'
9
9
  gem 'hanami-api'
10
- gem 'hanami-router', '~> 2.0.0.alpha5'
10
+ gem 'hanami-router'
11
11
  gem 'multi_json'
12
12
  gem 'openapi_first', path: '../'
13
+ gem 'roda'
13
14
  gem 'sinatra'
14
15
  gem 'syro'
@@ -1,11 +1,11 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- openapi_first (0.15.0)
4
+ openapi_first (0.19.0)
5
5
  deep_merge (>= 1.2.1)
6
- hanami-router (~> 2.0.alpha5)
7
- hanami-utils (~> 2.0.alpha3)
8
- json_refs (>= 0.1.7)
6
+ hanami-router (= 2.0.alpha5)
7
+ hanami-utils (= 2.0.alpha3)
8
+ json_refs (~> 0.1, >= 0.1.7)
9
9
  json_schemer (~> 0.2.16)
10
10
  multi_json (~> 1.14)
11
11
  rack (~> 2.2)
@@ -13,12 +13,12 @@ PATH
13
13
  GEM
14
14
  remote: https://rubygems.org/
15
15
  specs:
16
- activesupport (7.0.2.2)
16
+ activesupport (7.0.2.3)
17
17
  concurrent-ruby (~> 1.0, >= 1.0.2)
18
18
  i18n (>= 1.6, < 2)
19
19
  minitest (>= 5.1)
20
20
  tzinfo (~> 2.0)
21
- benchmark-ips (2.9.3)
21
+ benchmark-ips (2.10.0)
22
22
  benchmark-memory (0.2.0)
23
23
  memory_profiler (~> 1)
24
24
  builder (3.2.4)
@@ -26,7 +26,7 @@ GEM
26
26
  json_schema (~> 0.14, >= 0.14.3)
27
27
  openapi_parser (>= 0.11.1, < 1.0)
28
28
  rack (>= 1.5)
29
- concurrent-ruby (1.1.9)
29
+ concurrent-ruby (1.1.10)
30
30
  deep_merge (1.2.2)
31
31
  dry-configurable (0.14.0)
32
32
  concurrent-ruby (~> 1.0)
@@ -63,16 +63,16 @@ GEM
63
63
  mustermann (~> 1.0)
64
64
  mustermann-contrib (~> 1.0)
65
65
  rack (~> 2.0)
66
- hanami-utils (2.0.0.alpha6)
66
+ hanami-utils (2.0.0.alpha3)
67
67
  concurrent-ruby (~> 1.0)
68
68
  dry-transformer (~> 0.1)
69
69
  hansi (0.2.0)
70
- i18n (1.9.1)
70
+ i18n (1.10.0)
71
71
  concurrent-ruby (~> 1.0)
72
72
  json_refs (0.1.7)
73
73
  hana
74
74
  json_schema (0.21.0)
75
- json_schemer (0.2.18)
75
+ json_schemer (0.2.21)
76
76
  ecma-re-validator (~> 0.3)
77
77
  hana (~> 1.3)
78
78
  regexp_parser (~> 2.0)
@@ -88,18 +88,20 @@ GEM
88
88
  mustermann-grape (1.0.1)
89
89
  mustermann (>= 1.0.0)
90
90
  openapi_parser (0.15.0)
91
- rack (2.2.3)
91
+ rack (2.2.3.1)
92
92
  rack-accept (0.4.5)
93
93
  rack (>= 0.4)
94
- rack-protection (2.1.0)
94
+ rack-protection (2.2.0)
95
+ rack
96
+ regexp_parser (2.5.0)
97
+ roda (3.54.0)
95
98
  rack
96
- regexp_parser (2.2.1)
97
99
  ruby2_keywords (0.0.5)
98
100
  seg (1.2.0)
99
- sinatra (2.1.0)
101
+ sinatra (2.2.0)
100
102
  mustermann (~> 1.0)
101
103
  rack (~> 2.2)
102
- rack-protection (= 2.1.0)
104
+ rack-protection (= 2.2.0)
103
105
  tilt (~> 2.0)
104
106
  syro (3.2.1)
105
107
  rack (>= 1.6.0)
@@ -110,7 +112,8 @@ GEM
110
112
  uri_template (0.7.0)
111
113
 
112
114
  PLATFORMS
113
- x86_64-darwin-20
115
+ arm64-darwin-21
116
+ x86_64-linux
114
117
 
115
118
  DEPENDENCIES
116
119
  benchmark-ips
@@ -118,11 +121,12 @@ DEPENDENCIES
118
121
  committee
119
122
  grape
120
123
  hanami-api
121
- hanami-router (~> 2.0.0.alpha5)
124
+ hanami-router
122
125
  multi_json
123
126
  openapi_first!
127
+ roda
124
128
  sinatra
125
129
  syro
126
130
 
127
131
  BUNDLED WITH
128
- 2.2.28
132
+ 2.3.10
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'roda'
4
+ require 'multi_json'
5
+
6
+ class App < Roda
7
+ route do |r|
8
+ r.on 'hello' do
9
+ r.on :id do
10
+ r.get do
11
+ MultiJson.dump({ hello: 'world', id: r.params[:id] })
12
+ end
13
+ end
14
+
15
+ r.get do
16
+ MultiJson.dump([{ hello: 'world' }])
17
+ end
18
+
19
+ r.post do
20
+ response.status = 201
21
+ MultiJson.dump({ hello: 'world' })
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ run App.freeze.app
@@ -37,9 +37,7 @@ module OpenapiFirst
37
37
  module_name, klass_name = name.split('#')
38
38
  const = find_const(@namespace, module_name)
39
39
  klass = find_const(const, klass_name)
40
- return ->(params, res) { klass.new.call(params, res) } if klass.instance_method(:initialize).arity.zero?
41
-
42
- ->(params, res) { klass.new(params.env).call(params, res) }
40
+ klass.new
43
41
  end
44
42
 
45
43
  def find_const(parent, name)
@@ -47,9 +47,8 @@ module OpenapiFirst
47
47
  end
48
48
  end
49
49
 
50
- def content_type_for(status)
51
- content = response_for(status)['content']
52
- content.keys[0] if content
50
+ def content_types_for(status)
51
+ response_for(status)['content']&.keys
53
52
  end
54
53
 
55
54
  def response_schema_for(status, content_type)
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack'
4
+ require 'multi_json'
5
+ require_relative 'inbox'
6
+ require_relative 'default_operation_resolver'
7
+
8
+ module OpenapiFirst
9
+ class RackResponder
10
+ def initialize(namespace: nil, resolver: nil)
11
+ @resolver = resolver || DefaultOperationResolver.new(namespace)
12
+ @namespace = namespace
13
+ end
14
+
15
+ def call(env)
16
+ operation = env[OpenapiFirst::OPERATION]
17
+ find_handler(operation)&.call(env)
18
+ end
19
+
20
+ private
21
+
22
+ def find_handler(operation)
23
+ handler = @resolver.call(operation)
24
+ raise NotImplementedError, "Could not find handler for #{operation.name}" unless handler
25
+
26
+ handler
27
+ end
28
+
29
+ def serialize(result)
30
+ return result if result.is_a?(String)
31
+
32
+ MultiJson.dump(result)
33
+ end
34
+ end
35
+ end
@@ -10,9 +10,9 @@ module OpenapiFirst
10
10
  class RequestValidation # rubocop:disable Metrics/ClassLength
11
11
  prepend RouterRequired
12
12
 
13
- def initialize(app, raise_error: false)
13
+ def initialize(app, options = {})
14
14
  @app = app
15
- @raise = raise_error
15
+ @raise = options.fetch(:raise_error, false)
16
16
  end
17
17
 
18
18
  def call(env) # rubocop:disable Metrics/AbcSize
@@ -18,7 +18,7 @@ module OpenapiFirst
18
18
  handler = find_handler(operation)
19
19
  result = handler.call(env[INBOX], res)
20
20
  res.write serialize(result) if result && res.body.empty?
21
- res[Rack::CONTENT_TYPE] ||= operation.content_type_for(res.status)
21
+ res[Rack::CONTENT_TYPE] ||= operation.content_types_for(res.status)&.first
22
22
  res.finish
23
23
  end
24
24
 
@@ -7,15 +7,13 @@ module OpenapiFirst
7
7
  class Router
8
8
  def initialize(
9
9
  app,
10
- spec:,
11
- raise_error: false,
12
- not_found: :halt,
13
- parent_app: nil
10
+ options
14
11
  )
15
12
  @app = app
16
- @parent_app = parent_app
17
- @raise = raise_error
18
- @not_found = not_found
13
+ @parent_app = options.fetch(:parent_app, nil)
14
+ @raise = options.fetch(:raise_error, false)
15
+ @not_found = options.fetch(:not_found, :halt)
16
+ spec = options.fetch(:spec)
19
17
  @filepath = spec.filepath
20
18
  @router = build_router(spec.operations)
21
19
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OpenapiFirst
4
- VERSION = '0.16.0'
4
+ VERSION = '0.19.0'
5
5
  end
data/lib/openapi_first.rb CHANGED
@@ -20,7 +20,7 @@ module OpenapiFirst
20
20
  HANDLER = 'openapi_first.handler'
21
21
 
22
22
  def self.env
23
- ENV['RACK_ENV'] || ENV['HANAMI_ENV'] || ENV['RAILS_ENV']
23
+ ENV['RACK_ENV'] || ENV['HANAMI_ENV'] || ENV.fetch('RAILS_ENV', nil)
24
24
  end
25
25
 
26
26
  def self.load(spec_path, only: nil)
@@ -35,9 +35,9 @@ Gem::Specification.new do |spec|
35
35
  spec.required_ruby_version = '>= 2.6.0'
36
36
 
37
37
  spec.add_runtime_dependency 'deep_merge', '>= 1.2.1'
38
- spec.add_runtime_dependency 'hanami-router', '~> 2.0.alpha5'
39
- spec.add_runtime_dependency 'hanami-utils', '~> 2.0.alpha3'
40
- spec.add_runtime_dependency 'json_refs', '>= 0.1.7'
38
+ spec.add_runtime_dependency 'hanami-router', '2.0.alpha5'
39
+ spec.add_runtime_dependency 'hanami-utils', '2.0.alpha3'
40
+ spec.add_runtime_dependency 'json_refs', '~> 0.1', '>= 0.1.7'
41
41
  spec.add_runtime_dependency 'json_schemer', '~> 0.2.16'
42
42
  spec.add_runtime_dependency 'multi_json', '~> 1.14'
43
43
  spec.add_runtime_dependency 'rack', '~> 2.2'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openapi_first
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andreas Haller
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-04-05 00:00:00.000000000 Z
11
+ date: 2022-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deep_merge
@@ -28,34 +28,37 @@ dependencies:
28
28
  name: hanami-router
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - '='
32
32
  - !ruby/object:Gem::Version
33
33
  version: 2.0.alpha5
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - '='
39
39
  - !ruby/object:Gem::Version
40
40
  version: 2.0.alpha5
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: hanami-utils
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - '='
46
46
  - !ruby/object:Gem::Version
47
47
  version: 2.0.alpha3
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - '='
53
53
  - !ruby/object:Gem::Version
54
54
  version: 2.0.alpha3
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: json_refs
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.1'
59
62
  - - ">="
60
63
  - !ruby/object:Gem::Version
61
64
  version: 0.1.7
@@ -63,6 +66,9 @@ dependencies:
63
66
  prerelease: false
64
67
  version_requirements: !ruby/object:Gem::Requirement
65
68
  requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '0.1'
66
72
  - - ">="
67
73
  - !ruby/object:Gem::Version
68
74
  version: 0.1.7
@@ -194,6 +200,7 @@ files:
194
200
  - benchmarks/apps/openapi_first.ru
195
201
  - benchmarks/apps/openapi_first_with_hanami_api.ru
196
202
  - benchmarks/apps/openapi_first_with_response_validation.ru
203
+ - benchmarks/apps/roda.ru
197
204
  - benchmarks/apps/sinatra.ru
198
205
  - benchmarks/apps/syro.ru
199
206
  - benchmarks/benchmarks.rb
@@ -210,6 +217,7 @@ files:
210
217
  - lib/openapi_first/definition.rb
211
218
  - lib/openapi_first/inbox.rb
212
219
  - lib/openapi_first/operation.rb
220
+ - lib/openapi_first/rack_responder.rb
213
221
  - lib/openapi_first/request_validation.rb
214
222
  - lib/openapi_first/responder.rb
215
223
  - lib/openapi_first/response_object.rb