openapi_first 1.0.0.beta3 → 1.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 800354f7ac2847fb16987e6961589aaebb84c161f3b76ea652a00a4cf8762fbe
4
- data.tar.gz: f443b72fa8ce1103bfc5a7b30367ce96f84e0dc7ad137722424cab0ac0c13357
3
+ metadata.gz: c02c053192b6b39cb8f05acd35f7a257ee98b449c49f8ceeec4ac6e542f09e15
4
+ data.tar.gz: c36d3598b263ebd3d1a9bd23e6aa0b66256890f68e2f70fe245ca932d2f004f0
5
5
  SHA512:
6
- metadata.gz: e454ee38c95a21915869e5feae0f38f65e0aa9a0a5001b6b752043fa379836164af1bf7eac9bcff192822d66053dda00d6dfa787296cce82bccf346d218f4c6c
7
- data.tar.gz: 11a0a0ac1e1bbd350d1edfe1dcae4ccae15bcfe2f1863320f30f554c3ad16934b07891c578225d2d7d128c3cb7dafd4093407c1c153713567db4db3d9c99c938
6
+ metadata.gz: e70192d7c2cb58734b8ebb6ccf53b2f243a98e78adbea271a3b0df1468f400d60080ead1ea68c07dd33bd9985d67de02ec4e0200e3ca0d49272a893c97611ffb
7
+ data.tar.gz: c59e62cd24dd767330f7e9ce6ad96a9c13005a4498c39f3ccf10bc801b49b6bddccf3ac62f858ae3ecf56fa4c695b4ad010fea7292171f98b640dec968ea357d
@@ -1,24 +1,12 @@
1
- name: Ruby
2
-
3
- on:
4
- push:
5
- branches: [ master ]
6
- pull_request:
7
- branches: [ master ]
8
-
1
+ name: Test
2
+ on: [push, pull_request]
9
3
  jobs:
10
- build:
11
-
4
+ test:
12
5
  runs-on: ubuntu-latest
13
-
14
6
  steps:
15
- - uses: actions/checkout@v2
16
- - name: Set up Ruby 2.6
17
- uses: actions/setup-ruby@v1
7
+ - uses: actions/checkout@v3
8
+ - uses: ruby/setup-ruby@v1
18
9
  with:
19
- ruby-version: 2.6.x
20
- - name: Build and test with Rake
21
- run: |
22
- gem install bundler
23
- bundle install --jobs 4 --retry 3
24
- bundle exec rake
10
+ ruby-version: '3.1'
11
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
12
+ - run: bundle exec rake
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 3.0.5
2
+ TargetRubyVersion: 3.1.1
3
3
  NewCops: enable
4
4
  SuggestExtensions: false
5
5
  Style/Documentation:
data/CHANGELOG.md CHANGED
@@ -2,15 +2,28 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 1.0.0.beta4
6
+
7
+ - Update json_schemer to version 2.0
8
+ - Breaking: Requires Ruby 3.1 or later
9
+ - Added: Parameters are available at `env[OpenapiFirst::PATH_PARAMS]`, `env[OpenapiFirst::QUERY_PARAMS]`, `env[OpenapiFirst::HEADER_PARAMS]`, `env[OpenapiFirst::COOKIE_PARAMS]` in case you need to access them separately. Merged path and query parameters are still available at `env[OpenapiFirst::PARAMS]`
10
+ - Breaking / Added: ResponseValidation now validates response headers
11
+ - Breaking / Added: RequestValidation now validates cookie, path and header parameters
12
+ - Breaking: multipart File uploads are now read and then validated
13
+ - Breaking: Remove OpenapiFirst.env method
14
+ - Breaking: Request validation returns 400 instead of 415 if request body is required, but empty
15
+
5
16
  ## 1.0.0.beta3
6
17
 
7
18
  - Remove obsolete dependency: deep_merge
8
19
  - Remove obsolete dependency: hanami-utils
9
20
 
10
21
  ## 1.0.0.beta2
22
+
11
23
  - Fixed dependencies. Remove unused code.
12
24
 
13
25
  ## 1.0.0.beta1
26
+
14
27
  - Removed: `OpenapiFirst::Responder` and `OpenapiFirst::RackResponder`
15
28
  - Removed: `OpenapiFirst.app` and `OpenapiFirst.middleware`
16
29
  - Removed: `OpenapiFirst::Coverage`
data/Gemfile CHANGED
@@ -6,6 +6,9 @@ source 'https://rubygems.org'
6
6
  gemspec
7
7
 
8
8
  group :test, :development do
9
- gem 'pry'
9
+ gem 'bundler'
10
+ gem 'rack-test'
11
+ gem 'rake'
12
+ gem 'rspec'
10
13
  gem 'rubocop'
11
14
  end
data/Gemfile.lock CHANGED
@@ -1,22 +1,20 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openapi_first (1.0.0.beta3)
4
+ openapi_first (1.0.0.beta4)
5
5
  hanami-router (~> 2.0.0)
6
6
  json_refs (~> 0.1, >= 0.1.7)
7
- json_schemer (~> 0.2.16)
7
+ json_schemer (~> 2.0.0)
8
8
  multi_json (~> 1.14)
9
- openapi_parameters (~> 0.2)
9
+ openapi_parameters (~> 0.2.2)
10
10
  rack (>= 2.2, < 4.0)
11
11
 
12
12
  GEM
13
13
  remote: https://rubygems.org/
14
14
  specs:
15
15
  ast (2.4.2)
16
- coderay (1.1.3)
16
+ base64 (0.1.1)
17
17
  diff-lcs (1.5.0)
18
- ecma-re-validator (0.4.0)
19
- regexp_parser (~> 2.2)
20
18
  hana (1.3.7)
21
19
  hanami-router (2.0.2)
22
20
  mustermann (~> 3.0)
@@ -24,77 +22,81 @@ GEM
24
22
  rack (~> 2.0)
25
23
  hansi (0.2.1)
26
24
  json (2.6.3)
27
- json_refs (0.1.7)
25
+ json_refs (0.1.8)
28
26
  hana
29
- json_schemer (0.2.24)
30
- ecma-re-validator (~> 0.3)
27
+ json_schemer (2.0.0)
31
28
  hana (~> 1.3)
32
29
  regexp_parser (~> 2.0)
33
- uri_template (~> 0.7)
34
- method_source (1.0.0)
30
+ simpleidn (~> 0.2)
31
+ language_server-protocol (3.17.0.3)
35
32
  multi_json (1.15.0)
36
33
  mustermann (3.0.0)
37
34
  ruby2_keywords (~> 0.0.1)
38
35
  mustermann-contrib (3.0.0)
39
36
  hansi (~> 0.2.0)
40
37
  mustermann (= 3.0.0)
41
- openapi_parameters (0.2.1)
38
+ openapi_parameters (0.2.2)
42
39
  rack (>= 2.2)
43
40
  zeitwerk (~> 2.6)
44
- parallel (1.22.1)
45
- parser (3.2.1.1)
41
+ parallel (1.23.0)
42
+ parser (3.2.2.3)
46
43
  ast (~> 2.4.1)
47
- pry (0.14.2)
48
- coderay (~> 1.1)
49
- method_source (~> 1.0)
50
- rack (2.2.6.4)
51
- rack-test (1.1.0)
52
- rack (>= 1.0, < 3)
44
+ racc
45
+ racc (1.7.1)
46
+ rack (2.2.8)
47
+ rack-test (2.1.0)
48
+ rack (>= 1.3)
53
49
  rainbow (3.1.1)
54
50
  rake (13.0.6)
55
- regexp_parser (2.7.0)
56
- rexml (3.2.5)
51
+ regexp_parser (2.8.1)
52
+ rexml (3.2.6)
57
53
  rspec (3.12.0)
58
54
  rspec-core (~> 3.12.0)
59
55
  rspec-expectations (~> 3.12.0)
60
56
  rspec-mocks (~> 3.12.0)
61
- rspec-core (3.12.1)
57
+ rspec-core (3.12.2)
62
58
  rspec-support (~> 3.12.0)
63
- rspec-expectations (3.12.2)
59
+ rspec-expectations (3.12.3)
64
60
  diff-lcs (>= 1.2.0, < 2.0)
65
61
  rspec-support (~> 3.12.0)
66
- rspec-mocks (3.12.5)
62
+ rspec-mocks (3.12.6)
67
63
  diff-lcs (>= 1.2.0, < 2.0)
68
64
  rspec-support (~> 3.12.0)
69
- rspec-support (3.12.0)
70
- rubocop (1.48.1)
65
+ rspec-support (3.12.1)
66
+ rubocop (1.56.3)
67
+ base64 (~> 0.1.1)
71
68
  json (~> 2.3)
69
+ language_server-protocol (>= 3.17.0)
72
70
  parallel (~> 1.10)
73
- parser (>= 3.2.0.0)
71
+ parser (>= 3.2.2.3)
74
72
  rainbow (>= 2.2.2, < 4.0)
75
73
  regexp_parser (>= 1.8, < 3.0)
76
74
  rexml (>= 3.2.5, < 4.0)
77
- rubocop-ast (>= 1.26.0, < 2.0)
75
+ rubocop-ast (>= 1.28.1, < 2.0)
78
76
  ruby-progressbar (~> 1.7)
79
77
  unicode-display_width (>= 2.4.0, < 3.0)
80
- rubocop-ast (1.28.0)
78
+ rubocop-ast (1.29.0)
81
79
  parser (>= 3.2.1.0)
82
80
  ruby-progressbar (1.13.0)
83
81
  ruby2_keywords (0.0.5)
82
+ simpleidn (0.2.1)
83
+ unf (~> 0.1.4)
84
+ unf (0.1.4)
85
+ unf_ext
86
+ unf_ext (0.0.8.2)
84
87
  unicode-display_width (2.4.2)
85
- uri_template (0.7.0)
86
- zeitwerk (2.6.7)
88
+ zeitwerk (2.6.11)
87
89
 
88
90
  PLATFORMS
89
91
  arm64-darwin-21
92
+ x86_64-linux
90
93
 
91
94
  DEPENDENCIES
92
- bundler (~> 2)
95
+ bundler
93
96
  openapi_first!
94
- pry
95
- rack-test (~> 1)
96
- rake (~> 13)
97
- rspec (~> 3)
97
+ rack-test
98
+ rake
99
+ rspec
98
100
  rubocop
99
101
 
100
102
  BUNDLED WITH
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Join the chat at https://gitter.im/openapi_first/community](https://badges.gitter.im/openapi_first/community.svg)](https://gitter.im/openapi_first/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
4
 
5
- OpenapiFirst helps to implement HTTP APIs based on an [OpenAPI](https://www.openapis.org/) API description.
5
+ OpenapiFirst helps to implement HTTP APIs based on an [OpenAPI](https://www.openapis.org/) API description. It supports OpenAPI 3.0 and 3.1.
6
6
 
7
7
  It provides these Rack middlewares:
8
8
 
@@ -10,6 +10,8 @@ It provides these Rack middlewares:
10
10
  - [`OpenapiFirst::ResponseValidation`](#response-validation) Validates the response and raises an exception if the response body is invalid.
11
11
  - [`OpenapiFirst::Router`](#openapifirstrouter) – This internal middleware is added automatically when using request/response validation. It adds the OpenAPI operation for the current request to the Rack env.
12
12
 
13
+ Using Request and Response validation together ensures that your implementation follows exactly the API description. This enables you to use the API description as a single source of truth for your API, reason about details and use various tooling.
14
+
13
15
  ## Request Validation
14
16
 
15
17
  The `OpenapiFirst::RequestValidation` middleware returns a 400 status code with a body that describes the error if the request is not valid.
@@ -19,6 +21,7 @@ use OpenapiFirst::RequestValidation, spec: 'openapi.yaml'
19
21
  ```
20
22
 
21
23
  It adds these fields to the Rack env:
24
+
22
25
  - `env[OpenapiFirst::PARAMS]` – The parsed parameters (query, path) for the current request (string keyed)
23
26
  - `env[OpenapiFirst::REQUEST_BODY]` – The parsed request body (string keyed)
24
27
  - `env[OpenapiFirst::OPERATION]` (Added via Router) – The Operation object for the current request. This is an instance of `OpenapiFirst::Operation`.
@@ -27,8 +30,9 @@ It adds these fields to the Rack env:
27
30
 
28
31
  | Name | Possible values | Description | Default |
29
32
  | :------------- | --------------- | -------------------------------------------------------------------------------------------------- | ---------------------------------- |
30
- | `spec:` | | The path to the spec file or spec loaded via `OpenapiFirst.load`
33
+ | `spec:` | | The path to the spec file or spec loaded via `OpenapiFirst.load` |
31
34
  | `raise_error:` | `false`, `true` | If set to true the middleware raises `OpenapiFirst::RequestInvalidError` instead of returning 4xx. | `false` (don't raise an exception) |
35
+ | `error_response:`| `:default`, Your implementation of `ErrorResponse` | :default
32
36
 
33
37
  The error responses conform with [JSON:API](https://jsonapi.org).
34
38
 
@@ -50,6 +54,7 @@ content-type: "application/vnd.api+json"
50
54
  }
51
55
  ```
52
56
 
57
+
53
58
  ### Parameters
54
59
 
55
60
  The `RequestValidation` middleware adds `env[OpenapiFirst::PARAMS]` (or `env['openapi.params']` ) with the converted query and path parameters. This only includes the parameters that are defined in the API description. It supports every [`style` and `explode` value as described](https://spec.openapis.org/oas/latest.html#style-examples) in the OpenAPI 3.0 and 3.1 specs. So you can do things these:
@@ -72,9 +77,10 @@ This middleware adds the parsed request body to `env[OpenapiFirst::REQUEST_BODY]
72
77
 
73
78
  The middleware will return a status `415` if the requests content type does not match or `400` if the request body is invalid.
74
79
 
75
- ### Header, Cookie, Path parameter validation
80
+ ### Header, Cookie, Query and Path parameter validation
76
81
 
77
- tbd.
82
+ The `RequestValidation` middleware validates the request headers, cookies and path parameters as defined in you API description. It returns a `400` status code if the request is invalid. It adds the parsed merged _path_ and _query_ parameters to `env['openapi.params']`.
83
+ Separate parsed parameters are made available by location at `env['openapi.path_params']`, `env['openapi.query']`, `env['openapi.headers']`, `env['openapi.cookies']` as well if you need to access them separately.
78
84
 
79
85
  ### readOnly / writeOnly properties
80
86
 
@@ -92,9 +98,9 @@ use OpenapiFirst::ResponseValidation, spec: 'openapi.yaml' if ENV['RACK_ENV'] ==
92
98
 
93
99
  ### Options
94
100
 
95
- | Name | Possible values | Description | Default |
96
- | :------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
97
- | `spec:` | | The path to the spec file or spec loaded via `OpenapiFirst.load`
101
+ | Name | Possible values | Description | Default |
102
+ | :------ | --------------- | ---------------------------------------------------------------- | ------- |
103
+ | `spec:` | | The path to the spec file or spec loaded via `OpenapiFirst.load` |
98
104
 
99
105
  ## OpenapiFirst::Router
100
106
 
@@ -104,13 +110,13 @@ This middleware is used automatically, but you can add it to the top of your mid
104
110
  use OpenapiFirst::Router, spec: './openapi/openapi.yaml'
105
111
  ```
106
112
 
107
- This middleware adds `env[OpenapiFirst::OPERATION]` which holds an Operation object that responds to `#operation_id`, `#path` (and `#[string]` to access raw fields).
113
+ This middleware adds `env['openapi.operation']` which holds an instance of `OpenapiFirst::Operation` that responds to `#operation_id`, `#path` (and `#[]` to access raw fields).
108
114
 
109
115
  ### Options and defaults
110
116
 
111
117
  | Name | Possible values | Description | Default |
112
118
  | :------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
113
- | `spec:` | | The path to the spec file or spec loaded via `OpenapiFirst.load` | |
119
+ | `spec:` | | The path to the spec file or spec loaded via `OpenapiFirst.load` | |
114
120
  | `raise_error:` | `false`, `true` | If set to true the middleware raises `OpenapiFirst::NotFoundError` when a path or method was not found in the API description. This is useful during testing to spot an incomplete API description. | `false` (don't raise an exception) |
115
121
  | `not_found:` | `:continue`, `:halt` | If set to `:continue` the middleware will not return 404 (405, 415), but just pass handling the request to the next middleware or application in the Rack stack. If combined with `raise_error: true` `raise_error` gets preference and an exception is raised. | `:halt` (return 4xx response) |
116
122
 
@@ -160,9 +166,9 @@ run OpenapiFirst.app(spec, namespace: Pets)
160
166
 
161
167
  Run `bin/setup` to install dependencies.
162
168
 
163
- Run `bundle exec rspec` to run the tests.
169
+ See `bundle exec rake` to run the linter and the tests.
164
170
 
165
- See `bundle exec rake -T` for rubygems related tasks.
171
+ Run `bundle exec rspec` to run the tests only.
166
172
 
167
173
  ## Benchmarks
168
174
 
@@ -4,15 +4,15 @@ PATH
4
4
  openapi_first (1.0.0.beta3)
5
5
  hanami-router (~> 2.0.0)
6
6
  json_refs (~> 0.1, >= 0.1.7)
7
- json_schemer (~> 0.2.16)
7
+ json_schemer (~> 2.0.0)
8
8
  multi_json (~> 1.14)
9
- openapi_parameters (~> 0.2)
9
+ openapi_parameters (~> 0.2.2)
10
10
  rack (>= 2.2, < 4.0)
11
11
 
12
12
  GEM
13
13
  remote: https://rubygems.org/
14
14
  specs:
15
- activesupport (7.0.4.3)
15
+ activesupport (7.0.8)
16
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
17
17
  i18n (>= 1.6, < 2)
18
18
  minitest (>= 5.1)
@@ -40,14 +40,12 @@ GEM
40
40
  dry-inflector (~> 1.0)
41
41
  dry-logic (~> 1.4)
42
42
  zeitwerk (~> 2.6)
43
- ecma-re-validator (0.4.0)
44
- regexp_parser (~> 2.2)
45
- grape (1.7.0)
43
+ grape (1.7.1)
46
44
  activesupport
47
45
  builder
48
46
  dry-types (>= 1.1)
49
47
  mustermann-grape (~> 1.0.0)
50
- rack (>= 1.3.0)
48
+ rack (>= 1.3.0, < 3)
51
49
  rack-accept
52
50
  hana (1.3.7)
53
51
  hanami-api (0.3.0)
@@ -57,18 +55,17 @@ GEM
57
55
  mustermann-contrib (~> 3.0)
58
56
  rack (~> 2.0)
59
57
  hansi (0.2.1)
60
- i18n (1.12.0)
58
+ i18n (1.14.1)
61
59
  concurrent-ruby (~> 1.0)
62
- json_refs (0.1.7)
60
+ json_refs (0.1.8)
63
61
  hana
64
62
  json_schema (0.21.0)
65
- json_schemer (0.2.24)
66
- ecma-re-validator (~> 0.3)
63
+ json_schemer (2.0.0)
67
64
  hana (~> 1.3)
68
65
  regexp_parser (~> 2.0)
69
- uri_template (~> 0.7)
66
+ simpleidn (~> 0.2)
70
67
  memory_profiler (1.0.1)
71
- minitest (5.18.0)
68
+ minitest (5.20.0)
72
69
  multi_json (1.15.0)
73
70
  mustermann (3.0.0)
74
71
  ruby2_keywords (~> 0.0.1)
@@ -78,22 +75,24 @@ GEM
78
75
  mustermann-grape (1.0.2)
79
76
  mustermann (>= 1.0.0)
80
77
  nio4r (2.5.9)
81
- openapi_parameters (0.2.1)
78
+ openapi_parameters (0.2.2)
82
79
  rack (>= 2.2)
83
80
  zeitwerk (~> 2.6)
84
81
  openapi_parser (1.0.0)
85
- puma (6.2.2)
82
+ puma (6.3.1)
86
83
  nio4r (~> 2.0)
87
- rack (2.2.6.4)
84
+ rack (2.2.8)
88
85
  rack-accept (0.4.5)
89
86
  rack (>= 0.4)
90
87
  rack-protection (3.0.6)
91
88
  rack
92
- regexp_parser (2.8.0)
93
- roda (3.67.0)
89
+ regexp_parser (2.8.1)
90
+ roda (3.68.0)
94
91
  rack
95
92
  ruby2_keywords (0.0.5)
96
93
  seg (1.2.0)
94
+ simpleidn (0.2.1)
95
+ unf (~> 0.1.4)
97
96
  sinatra (3.0.6)
98
97
  mustermann (~> 3.0)
99
98
  rack (~> 2.2, >= 2.2.4)
@@ -105,8 +104,10 @@ GEM
105
104
  tilt (2.1.0)
106
105
  tzinfo (2.0.6)
107
106
  concurrent-ruby (~> 1.0)
108
- uri_template (0.7.0)
109
- zeitwerk (2.6.7)
107
+ unf (0.1.4)
108
+ unf_ext
109
+ unf_ext (0.0.8.2)
110
+ zeitwerk (2.6.11)
110
111
 
111
112
  PLATFORMS
112
113
  arm64-darwin-21
@@ -24,9 +24,9 @@ app = Rack::Builder.new do
24
24
 
25
25
  not_found = ->(_env) { [404, {}, []] }
26
26
 
27
- run lambda do |env|
27
+ run(lambda do |env|
28
28
  handlers.fetch(env[OpenapiFirst::OPERATION]&.operation_id, not_found).call(env)
29
- end
29
+ end)
30
30
  end
31
31
 
32
32
  run app
@@ -23,7 +23,7 @@ module OpenapiFirst
23
23
  errors = [err]
24
24
 
25
25
  Rack::Response.new(
26
- MultiJson.dump(errors: errors),
26
+ MultiJson.dump(errors:),
27
27
  400,
28
28
  Rack::CONTENT_TYPE => 'application/vnd.api+json'
29
29
  ).finish
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenapiFirst
4
+ class Config
5
+ def initialize(error_response: :default)
6
+ @error_response = error_response
7
+ end
8
+
9
+ attr_reader :error_response
10
+
11
+ def self.default_options
12
+ @default_options ||= new
13
+ end
14
+
15
+ def self.default_options=(options)
16
+ @default_options = new(**options)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenapiFirst
4
+ class DefaultErrorResponse < ErrorResponse
5
+ OpenapiFirst::Plugins.register_error_response(:default, self)
6
+
7
+ def body
8
+ MultiJson.dump({ errors: serialized_errors })
9
+ end
10
+
11
+ def serialized_errors
12
+ return default_errors unless validation_output
13
+
14
+ key = pointer_key
15
+ [
16
+ {
17
+ source: { key => pointer(validation_output['instanceLocation']) },
18
+ title: validation_output['error']
19
+ }
20
+ ]
21
+ end
22
+
23
+ def default_errors
24
+ [{
25
+ status: status.to_s,
26
+ title:
27
+ }]
28
+ end
29
+
30
+ def pointer_key
31
+ case location
32
+ when :request_body
33
+ :pointer
34
+ when :query, :path
35
+ :parameter
36
+ else
37
+ location
38
+ end
39
+ end
40
+
41
+ def pointer(data_pointer)
42
+ return data_pointer if location == :request_body
43
+
44
+ data_pointer.delete_prefix('/')
45
+ end
46
+ end
47
+ end
@@ -3,6 +3,7 @@
3
3
  require_relative 'operation'
4
4
 
5
5
  module OpenapiFirst
6
+ # Represents an OpenAPI API Description document
6
7
  class Definition
7
8
  attr_reader :filepath, :operations
8
9
 
@@ -11,9 +12,15 @@ module OpenapiFirst
11
12
  methods = %w[get head post put patch delete trace options]
12
13
  @operations = resolved['paths'].flat_map do |path, path_item|
13
14
  path_item.slice(*methods).map do |request_method, _operation_object|
14
- Operation.new(path, request_method, path_item)
15
+ Operation.new(path, request_method, path_item, openapi_version: detect_version(resolved))
15
16
  end
16
17
  end
17
18
  end
19
+
20
+ private
21
+
22
+ def detect_version(resolved)
23
+ (resolved['openapi'] || resolved['swagger'])[0..2]
24
+ end
18
25
  end
19
26
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenapiFirst
4
+ # This is the base class for error responses
5
+ class ErrorResponse
6
+ ## @param status [Integer] The HTTP status code.
7
+ ## @param title [String] The title of the error. Usually the name of the HTTP status code.
8
+ ## @param location [Symbol] The location of the error (:request_body, :query, :header, :cookie, :path).
9
+ ## @param validation_result [ValidationResult]
10
+ def initialize(status:, location:, title:, validation_result:)
11
+ @status = status
12
+ @title = title
13
+ @location = location
14
+ @validation_output = validation_result&.output
15
+ @schema = validation_result&.schema
16
+ @data = validation_result&.data
17
+ end
18
+
19
+ attr_reader :status, :location, :title, :schema, :data, :validation_output
20
+
21
+ def render
22
+ Rack::Response.new(body, status, Rack::CONTENT_TYPE => content_type).finish
23
+ end
24
+
25
+ def content_type = 'application/json'
26
+
27
+ def body
28
+ raise NotImplementedError
29
+ end
30
+ end
31
+ end
@@ -5,15 +5,6 @@ module OpenapiFirst
5
5
 
6
6
  class NotFoundError < Error; end
7
7
 
8
- class HandlerNotFoundError < Error; end
9
-
10
- class NotImplementedError < Error
11
- def initialize(message)
12
- warn 'NotImplementedError is deprecated. Handle HandlerNotFoundError instead'
13
- super
14
- end
15
- end
16
-
17
8
  class ResponseInvalid < Error; end
18
9
 
19
10
  class ResponseCodeNotFoundError < ResponseInvalid; end
@@ -22,37 +13,9 @@ module OpenapiFirst
22
13
 
23
14
  class ResponseBodyInvalidError < ResponseInvalid; end
24
15
 
16
+ class ResponseHeaderInvalidError < ResponseInvalid; end
17
+
25
18
  class BodyParsingError < Error; end
26
19
 
27
- class RequestInvalidError < Error
28
- def initialize(serialized_errors)
29
- message = error_message(serialized_errors)
30
- super message
31
- end
32
-
33
- private
34
-
35
- def error_message(errors)
36
- errors.map do |error|
37
- [human_source(error), human_error(error)].compact.join(' ')
38
- end.join(', ')
39
- end
40
-
41
- def human_source(error)
42
- return unless error[:source]
43
-
44
- source_key = error[:source].keys.first
45
- source = {
46
- pointer: 'Request body invalid:',
47
- parameter: 'Query parameter invalid:'
48
- }.fetch(source_key, source_key)
49
- name = error[:source].values.first
50
- source += " #{name}" unless name.nil? || name.empty?
51
- source
52
- end
53
-
54
- def human_error(error)
55
- error[:title]
56
- end
57
- end
20
+ class RequestInvalidError < Error; end
58
21
  end