openapi_first 0.12.2 → 0.13.2
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 +4 -4
- data/.rubocop.yml +20 -0
- data/CHANGELOG.md +17 -0
- data/Gemfile.lock +13 -13
- data/README.md +24 -2
- data/benchmarks/Gemfile.lock +12 -12
- data/examples/app.rb +2 -1
- data/lib/openapi_first.rb +29 -4
- data/lib/openapi_first/app.rb +11 -4
- data/lib/openapi_first/find_handler.rb +2 -4
- data/lib/openapi_first/operation.rb +14 -1
- data/lib/openapi_first/request_validation.rb +19 -4
- data/lib/openapi_first/router.rb +5 -1
- data/lib/openapi_first/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 579d36678fe6b41e050a370017165899c82be5e64b352e45410107e7302d26af
|
4
|
+
data.tar.gz: 0ddd3ab2f5ed7bb9aadc41cba158ea3fc9f2e59a93054c4f76f3766109e03192
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb1ca083cce9a636bf42f33c308dcd5c1e19b14b31bebe0534646baf0af8c43e6ce1d5b1e20b0657872a12c90e2446122a33c015ce42ee96ee16c8b1f4cc8b79
|
7
|
+
data.tar.gz: 8a2f1af143f23f21381691d158d0991b1e055d726c8e0c46579bd1d88383f3c4f66ca3a8b1554a47bdab5e6278340b6e6e8ace1d983e95b01b84c1f822a5249b
|
data/.rubocop.yml
CHANGED
@@ -14,6 +14,8 @@ Layout/SpaceAroundMethodCallOperator:
|
|
14
14
|
Enabled: true
|
15
15
|
Lint/DeprecatedOpenSSLConstant:
|
16
16
|
Enabled: true
|
17
|
+
Lint/DuplicateElsifCondition:
|
18
|
+
Enabled: true
|
17
19
|
Lint/RaiseException:
|
18
20
|
Enabled: true
|
19
21
|
Lint/MixedRegexpCaptureTypes:
|
@@ -28,7 +30,25 @@ Lint/StructNewOverride:
|
|
28
30
|
Enabled: true
|
29
31
|
Style/HashEachMethods:
|
30
32
|
Enabled: false
|
33
|
+
Style/AccessorGrouping:
|
34
|
+
Enabled: true
|
35
|
+
Style/ArrayCoercion:
|
36
|
+
Enabled: true
|
37
|
+
Style/BisectedAttrAccessor:
|
38
|
+
Enabled: true
|
39
|
+
Style/CaseLikeIf:
|
40
|
+
Enabled: true
|
41
|
+
Style/HashAsLastArrayItem:
|
42
|
+
Enabled: true
|
43
|
+
Style/HashLikeCase:
|
44
|
+
Enabled: true
|
31
45
|
Style/HashTransformKeys:
|
32
46
|
Enabled: true
|
33
47
|
Style/HashTransformValues:
|
34
48
|
Enabled: true
|
49
|
+
Style/RedundantAssignment:
|
50
|
+
Enabled: true
|
51
|
+
Style/RedundantFetchBlock:
|
52
|
+
Enabled: true
|
53
|
+
Style/RedundantFileExtensionInRequire:
|
54
|
+
Enabled: true
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.13.2
|
4
|
+
- Return indicator (`source: { parameter: 'list/1' }`) in error response body when array item in query parameter is invalid
|
5
|
+
|
6
|
+
## 0.13.0
|
7
|
+
- Add support for arrays in query parameters (style: form, explode: false)
|
8
|
+
- Remove warning when handler is not implemented
|
9
|
+
|
10
|
+
## 0.12.5
|
11
|
+
- Add `not_found: :continue` option to Router to make it do nothing if request is unknown
|
12
|
+
|
13
|
+
## 0.12.4
|
14
|
+
- content-type is found while ignoring additional content-type parameters (`application/json` is found when request/response content-type is `application/json; charset=UTF8`)
|
15
|
+
- Support wildcard mime-types when finding the content-type
|
16
|
+
|
17
|
+
## 0.12.3
|
18
|
+
- Add `response_validation:`, `router_raise_error` options to standalone mode.
|
19
|
+
|
3
20
|
## 0.12.2
|
4
21
|
- Allow response to have no media type object specified
|
5
22
|
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
openapi_first (0.
|
4
|
+
openapi_first (0.13.2)
|
5
5
|
deep_merge (>= 1.2.1)
|
6
6
|
hanami-router (~> 2.0.alpha3)
|
7
7
|
hanami-utils (~> 2.0.alpha1)
|
@@ -24,9 +24,9 @@ GEM
|
|
24
24
|
ast (2.4.1)
|
25
25
|
builder (3.2.4)
|
26
26
|
coderay (1.1.3)
|
27
|
-
concurrent-ruby (1.1.
|
27
|
+
concurrent-ruby (1.1.7)
|
28
28
|
deep_merge (1.2.1)
|
29
|
-
diff-lcs (1.4.
|
29
|
+
diff-lcs (1.4.4)
|
30
30
|
ecma-re-validator (0.2.1)
|
31
31
|
regexp_parser (~> 1.2)
|
32
32
|
hana (1.3.6)
|
@@ -39,9 +39,9 @@ GEM
|
|
39
39
|
transproc (~> 1.0)
|
40
40
|
hansi (0.2.0)
|
41
41
|
hash-deep-merge (0.1.1)
|
42
|
-
i18n (1.8.
|
42
|
+
i18n (1.8.5)
|
43
43
|
concurrent-ruby (~> 1.0)
|
44
|
-
json_schemer (0.2.
|
44
|
+
json_schemer (0.2.13)
|
45
45
|
ecma-re-validator (~> 0.2)
|
46
46
|
hana (~> 1.3)
|
47
47
|
regexp_parser (~> 1.5)
|
@@ -49,15 +49,15 @@ GEM
|
|
49
49
|
method_source (1.0.0)
|
50
50
|
mini_portile2 (2.4.0)
|
51
51
|
minitest (5.14.1)
|
52
|
-
multi_json (1.
|
52
|
+
multi_json (1.15.0)
|
53
53
|
mustermann (1.1.1)
|
54
54
|
ruby2_keywords (~> 0.0.1)
|
55
55
|
mustermann-contrib (1.1.1)
|
56
56
|
hansi (~> 0.2.0)
|
57
57
|
mustermann (= 1.1.1)
|
58
|
-
nokogiri (1.10.
|
58
|
+
nokogiri (1.10.10)
|
59
59
|
mini_portile2 (~> 2.4.0)
|
60
|
-
oas_parser (0.25.
|
60
|
+
oas_parser (0.25.1)
|
61
61
|
activesupport (>= 4.0.0)
|
62
62
|
addressable (~> 2.3)
|
63
63
|
builder (~> 3.2.3)
|
@@ -92,16 +92,16 @@ GEM
|
|
92
92
|
diff-lcs (>= 1.2.0, < 2.0)
|
93
93
|
rspec-support (~> 3.9.0)
|
94
94
|
rspec-support (3.9.3)
|
95
|
-
rubocop (0.
|
95
|
+
rubocop (0.88.0)
|
96
96
|
parallel (~> 1.10)
|
97
|
-
parser (>= 2.7.
|
97
|
+
parser (>= 2.7.1.1)
|
98
98
|
rainbow (>= 2.2.2, < 4.0)
|
99
99
|
regexp_parser (>= 1.7)
|
100
100
|
rexml
|
101
|
-
rubocop-ast (>= 0.0
|
101
|
+
rubocop-ast (>= 0.1.0, < 1.0)
|
102
102
|
ruby-progressbar (~> 1.7)
|
103
103
|
unicode-display_width (>= 1.4.0, < 2.0)
|
104
|
-
rubocop-ast (0.0
|
104
|
+
rubocop-ast (0.2.0)
|
105
105
|
parser (>= 2.7.0.1)
|
106
106
|
ruby-progressbar (1.10.1)
|
107
107
|
ruby2_keywords (0.0.2)
|
@@ -111,7 +111,7 @@ GEM
|
|
111
111
|
thread_safe (~> 0.1)
|
112
112
|
unicode-display_width (1.7.0)
|
113
113
|
uri_template (0.7.0)
|
114
|
-
zeitwerk (2.
|
114
|
+
zeitwerk (2.4.0)
|
115
115
|
|
116
116
|
PLATFORMS
|
117
117
|
ruby
|
data/README.md
CHANGED
@@ -37,6 +37,7 @@ Options and their defaults:
|
|
37
37
|
|:---|---|---|---|
|
38
38
|
|`spec:`| | The spec loaded via `OpenapiFirst.load` ||
|
39
39
|
| `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)
|
40
|
+
| `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)
|
40
41
|
|
41
42
|
## OpenapiFirst::RequestValidation
|
42
43
|
|
@@ -78,7 +79,12 @@ This middleware adds `env[OpenapiFirst::INBOX]` which holds the (filtered) path
|
|
78
79
|
### Parameter validation
|
79
80
|
|
80
81
|
The middleware filteres all top-level query parameters and paths parameters and tries to convert numeric values. Meaning, if you have an `:something_id` path with `type: integer`, it will try convert the value to an integer.
|
81
|
-
|
82
|
+
|
83
|
+
It just works with a parameter with `name: filter[age]`.
|
84
|
+
|
85
|
+
OpenapiFirst also supports `type: array` for query parameters and will convert `items` just as described above. [`style`](http://spec.openapis.org/oas/v3.0.3#style-values) and `explode` attributes are not supported for query parameters. It will always act as if `style: form` and `explode: false` were used for query parameters.
|
86
|
+
|
87
|
+
Conversion is currently done only for path and query parameters, but not for the request body. OpenapiFirst currently does not convert date, date-time or time formats.
|
82
88
|
|
83
89
|
If you want to forbid _nested_ query parameters you will need to use [`additionalProperties: false`](https://json-schema.org/understanding-json-schema/reference/object.html#properties) in your query parameter JSON schema.
|
84
90
|
|
@@ -150,7 +156,12 @@ end
|
|
150
156
|
|
151
157
|
# In config.ru:
|
152
158
|
require 'openapi_first'
|
153
|
-
run OpenapiFirst.app(
|
159
|
+
run OpenapiFirst.app(
|
160
|
+
'./openapi/openapi.yaml',
|
161
|
+
namespace: Pets,
|
162
|
+
response_validation: ENV['RACK_ENV'] == 'test',
|
163
|
+
router_raise_error: ENV['RACK_ENV'] == 'test'
|
164
|
+
)
|
154
165
|
```
|
155
166
|
|
156
167
|
The above will use the mentioned Rack middlewares to:
|
@@ -159,6 +170,17 @@ The above will use the mentioned Rack middlewares to:
|
|
159
170
|
- Map the request to a method call `Pets.find_pet` based on the `operationId` in the API description
|
160
171
|
- Set the response content type according to your spec (here with the default status code `200`)
|
161
172
|
|
173
|
+
### Options and their defaults:
|
174
|
+
|
175
|
+
| Name | Possible values | Description | Default
|
176
|
+
|:---|---|---|---|
|
177
|
+
| `spec_path` || A filepath to an OpenAPI definition file. |
|
178
|
+
| `namespace:` || A class or module where to find the handler methods.|
|
179
|
+
| `response_validation:` | `true`, `false` | If set to true it raises an exception if the response is invalid. This is useful during testing. | `false`
|
180
|
+
| `router_raise_error:` | `true`, `false` | If set to true it raises an exception (subclass of `OpenapiFirst::Error` when a request path/method is not specified. This is useful during testing. | `false`
|
181
|
+
| `request_validation_raise_error:` | `true`, `false` | If set to true it raises an exception (subclass of `OpenapiFirst::Error` when a request is not valid. | `false`
|
182
|
+
|
183
|
+
|
162
184
|
Handler functions (`find_pet`) are called with two arguments:
|
163
185
|
|
164
186
|
- `params` - Holds the parsed request body, filtered query params and path parameters
|
data/benchmarks/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
openapi_first (0.
|
4
|
+
openapi_first (0.13.2)
|
5
5
|
deep_merge (>= 1.2.1)
|
6
6
|
hanami-router (~> 2.0.alpha3)
|
7
7
|
hanami-utils (~> 2.0.alpha1)
|
@@ -25,11 +25,11 @@ GEM
|
|
25
25
|
benchmark-memory (0.1.2)
|
26
26
|
memory_profiler (~> 0.9)
|
27
27
|
builder (3.2.4)
|
28
|
-
committee (4.
|
28
|
+
committee (4.2.0)
|
29
29
|
json_schema (~> 0.14, >= 0.14.3)
|
30
30
|
openapi_parser (>= 0.11.1)
|
31
31
|
rack (>= 1.5)
|
32
|
-
concurrent-ruby (1.1.
|
32
|
+
concurrent-ruby (1.1.7)
|
33
33
|
deep_merge (1.2.1)
|
34
34
|
dry-configurable (0.11.6)
|
35
35
|
concurrent-ruby (~> 1.0)
|
@@ -42,7 +42,7 @@ GEM
|
|
42
42
|
concurrent-ruby (~> 1.0)
|
43
43
|
dry-equalizer (0.3.0)
|
44
44
|
dry-inflector (0.2.0)
|
45
|
-
dry-logic (1.0.
|
45
|
+
dry-logic (1.0.7)
|
46
46
|
concurrent-ruby (~> 1.0)
|
47
47
|
dry-core (~> 0.2)
|
48
48
|
dry-equalizer (~> 0.2)
|
@@ -55,7 +55,7 @@ GEM
|
|
55
55
|
dry-logic (~> 1.0, >= 1.0.2)
|
56
56
|
ecma-re-validator (0.2.1)
|
57
57
|
regexp_parser (~> 1.2)
|
58
|
-
grape (1.
|
58
|
+
grape (1.4.0)
|
59
59
|
activesupport
|
60
60
|
builder
|
61
61
|
dry-types (>= 1.1)
|
@@ -72,10 +72,10 @@ GEM
|
|
72
72
|
transproc (~> 1.0)
|
73
73
|
hansi (0.2.0)
|
74
74
|
hash-deep-merge (0.1.1)
|
75
|
-
i18n (1.8.
|
75
|
+
i18n (1.8.5)
|
76
76
|
concurrent-ruby (~> 1.0)
|
77
77
|
json_schema (0.20.9)
|
78
|
-
json_schemer (0.2.
|
78
|
+
json_schemer (0.2.13)
|
79
79
|
ecma-re-validator (~> 0.2)
|
80
80
|
hana (~> 1.3)
|
81
81
|
regexp_parser (~> 1.5)
|
@@ -83,7 +83,7 @@ GEM
|
|
83
83
|
memory_profiler (0.9.14)
|
84
84
|
mini_portile2 (2.4.0)
|
85
85
|
minitest (5.14.1)
|
86
|
-
multi_json (1.
|
86
|
+
multi_json (1.15.0)
|
87
87
|
mustermann (1.1.1)
|
88
88
|
ruby2_keywords (~> 0.0.1)
|
89
89
|
mustermann-contrib (1.1.1)
|
@@ -91,9 +91,9 @@ GEM
|
|
91
91
|
mustermann (= 1.1.1)
|
92
92
|
mustermann-grape (1.0.1)
|
93
93
|
mustermann (>= 1.0.0)
|
94
|
-
nokogiri (1.10.
|
94
|
+
nokogiri (1.10.10)
|
95
95
|
mini_portile2 (~> 2.4.0)
|
96
|
-
oas_parser (0.25.
|
96
|
+
oas_parser (0.25.1)
|
97
97
|
activesupport (>= 4.0.0)
|
98
98
|
addressable (~> 2.3)
|
99
99
|
builder (~> 3.2.3)
|
@@ -101,7 +101,7 @@ GEM
|
|
101
101
|
hash-deep-merge
|
102
102
|
mustermann-contrib (~> 1.1.1)
|
103
103
|
nokogiri
|
104
|
-
openapi_parser (0.
|
104
|
+
openapi_parser (0.12.1)
|
105
105
|
public_suffix (4.0.5)
|
106
106
|
rack (2.2.3)
|
107
107
|
rack-accept (0.4.5)
|
@@ -125,7 +125,7 @@ GEM
|
|
125
125
|
tzinfo (1.2.7)
|
126
126
|
thread_safe (~> 0.1)
|
127
127
|
uri_template (0.7.0)
|
128
|
-
zeitwerk (2.
|
128
|
+
zeitwerk (2.4.0)
|
129
129
|
|
130
130
|
PLATFORMS
|
131
131
|
ruby
|
data/examples/app.rb
CHANGED
@@ -17,5 +17,6 @@ oas_path = File.absolute_path('./openapi.yaml', __dir__)
|
|
17
17
|
App = OpenapiFirst.app(
|
18
18
|
oas_path,
|
19
19
|
namespace: Web,
|
20
|
-
|
20
|
+
router_raise_error: OpenapiFirst.env == 'test',
|
21
|
+
response_validation: OpenapiFirst.env == 'test'
|
21
22
|
)
|
data/lib/openapi_first.rb
CHANGED
@@ -31,14 +31,39 @@ module OpenapiFirst
|
|
31
31
|
Definition.new(parsed)
|
32
32
|
end
|
33
33
|
|
34
|
-
def self.app(
|
34
|
+
def self.app(
|
35
|
+
spec,
|
36
|
+
namespace:,
|
37
|
+
router_raise_error: false,
|
38
|
+
request_validation_raise_error: false,
|
39
|
+
response_validation: false
|
40
|
+
)
|
35
41
|
spec = OpenapiFirst.load(spec) if spec.is_a?(String)
|
36
|
-
App.new(
|
42
|
+
App.new(
|
43
|
+
nil,
|
44
|
+
spec,
|
45
|
+
namespace: namespace,
|
46
|
+
router_raise_error: router_raise_error,
|
47
|
+
request_validation_raise_error: request_validation_raise_error,
|
48
|
+
response_validation: response_validation
|
49
|
+
)
|
37
50
|
end
|
38
51
|
|
39
|
-
def self.middleware(
|
52
|
+
def self.middleware(
|
53
|
+
spec,
|
54
|
+
namespace:,
|
55
|
+
router_raise_error: false,
|
56
|
+
request_validation_raise_error: false,
|
57
|
+
response_validation: false
|
58
|
+
)
|
40
59
|
spec = OpenapiFirst.load(spec) if spec.is_a?(String)
|
41
|
-
AppWithOptions.new(
|
60
|
+
AppWithOptions.new(
|
61
|
+
spec,
|
62
|
+
namespace: namespace,
|
63
|
+
router_raise_error: router_raise_error,
|
64
|
+
request_validation_raise_error: request_validation_raise_error,
|
65
|
+
response_validation: response_validation
|
66
|
+
)
|
42
67
|
end
|
43
68
|
|
44
69
|
class AppWithOptions
|
data/lib/openapi_first/app.rb
CHANGED
@@ -5,12 +5,19 @@ require 'logger'
|
|
5
5
|
|
6
6
|
module OpenapiFirst
|
7
7
|
class App
|
8
|
-
def initialize(
|
8
|
+
def initialize( # rubocop:disable Metrics/ParameterLists
|
9
|
+
parent_app,
|
10
|
+
spec,
|
11
|
+
namespace:,
|
12
|
+
router_raise_error: false,
|
13
|
+
request_validation_raise_error: false,
|
14
|
+
response_validation: false
|
15
|
+
)
|
9
16
|
@stack = Rack::Builder.app do
|
10
17
|
freeze_app
|
11
|
-
use OpenapiFirst::Router, spec: spec, raise_error:
|
12
|
-
use OpenapiFirst::RequestValidation, raise_error:
|
13
|
-
use OpenapiFirst::ResponseValidation if
|
18
|
+
use OpenapiFirst::Router, spec: spec, raise_error: router_raise_error, parent_app: parent_app
|
19
|
+
use OpenapiFirst::RequestValidation, raise_error: request_validation_raise_error
|
20
|
+
use OpenapiFirst::ResponseValidation if response_validation
|
14
21
|
run OpenapiFirst::Responder.new(
|
15
22
|
spec: spec,
|
16
23
|
namespace: namespace
|
@@ -9,10 +9,8 @@ module OpenapiFirst
|
|
9
9
|
@handlers = spec.operations.each_with_object({}) do |operation, hash|
|
10
10
|
operation_id = operation.operation_id
|
11
11
|
handler = find_handler(operation_id)
|
12
|
-
if handler.nil?
|
13
|
-
|
14
|
-
next
|
15
|
-
end
|
12
|
+
next if handler.nil?
|
13
|
+
|
16
14
|
hash[operation_id] = handler
|
17
15
|
end
|
18
16
|
end
|
@@ -41,7 +41,7 @@ module OpenapiFirst
|
|
41
41
|
|
42
42
|
raise ResponseInvalid, "Response has no content-type for '#{name}'" unless content_type
|
43
43
|
|
44
|
-
media_type = content
|
44
|
+
media_type = find_content_for_content_type(content, content_type)
|
45
45
|
unless media_type
|
46
46
|
message = "Response content type not found '#{content_type}' for '#{name}'"
|
47
47
|
raise ResponseContentTypeNotFoundError, message
|
@@ -49,6 +49,12 @@ module OpenapiFirst
|
|
49
49
|
media_type['schema']
|
50
50
|
end
|
51
51
|
|
52
|
+
def request_body_schema_for(request_content_type)
|
53
|
+
content = @operation.request_body.content
|
54
|
+
media_type = find_content_for_content_type(content, request_content_type)
|
55
|
+
media_type&.fetch('schema', nil)
|
56
|
+
end
|
57
|
+
|
52
58
|
def response_for(status)
|
53
59
|
@operation.response_by_code(status.to_s, use_default: true).raw
|
54
60
|
rescue OasParser::ResponseCodeNotFound
|
@@ -62,6 +68,13 @@ module OpenapiFirst
|
|
62
68
|
|
63
69
|
private
|
64
70
|
|
71
|
+
def find_content_for_content_type(content, request_content_type)
|
72
|
+
content.fetch(request_content_type) do |_|
|
73
|
+
type = request_content_type.split(';')[0]
|
74
|
+
content[type] || content["#{type.split('/')[0]}/*"] || content['*/*']
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
65
78
|
def build_parameters_json_schema
|
66
79
|
return unless @operation.parameters&.any?
|
67
80
|
|
@@ -98,7 +98,8 @@ module OpenapiFirst
|
|
98
98
|
def request_body_schema(content_type, operation)
|
99
99
|
return unless operation
|
100
100
|
|
101
|
-
schema = operation.
|
101
|
+
schema = operation.request_body_schema_for(content_type)
|
102
|
+
|
102
103
|
JSONSchemer.schema(schema) if schema
|
103
104
|
end
|
104
105
|
|
@@ -140,8 +141,9 @@ module OpenapiFirst
|
|
140
141
|
|
141
142
|
def serialize_query_parameter_errors(validation_errors)
|
142
143
|
validation_errors.map do |error|
|
144
|
+
pointer = error['data_pointer'][1..].to_s
|
143
145
|
{
|
144
|
-
source: { parameter:
|
146
|
+
source: { parameter: pointer }
|
145
147
|
}.update(ValidationFormat.error_details(error))
|
146
148
|
end
|
147
149
|
end
|
@@ -149,14 +151,27 @@ module OpenapiFirst
|
|
149
151
|
def parse_parameter(value, schema)
|
150
152
|
return filtered_params(schema, value) if schema['properties']
|
151
153
|
|
154
|
+
return parse_array_parameter(value, schema) if schema['type'] == 'array'
|
155
|
+
|
156
|
+
parse_simple_value(value, schema)
|
157
|
+
end
|
158
|
+
|
159
|
+
def parse_array_parameter(value, schema)
|
160
|
+
array = value.is_a?(Array) ? value : value.split(',')
|
161
|
+
return array unless schema['items']
|
162
|
+
|
163
|
+
array.map! { |e| parse_simple_value(e, schema['items']) }
|
164
|
+
end
|
165
|
+
|
166
|
+
def parse_simple_value(value, schema)
|
167
|
+
return to_boolean(value) if schema['type'] == 'boolean'
|
168
|
+
|
152
169
|
begin
|
153
170
|
return Integer(value, 10) if schema['type'] == 'integer'
|
154
171
|
return Float(value) if schema['type'] == 'number'
|
155
172
|
rescue ArgumentError
|
156
173
|
value
|
157
174
|
end
|
158
|
-
return to_boolean(value) if schema['type'] == 'boolean'
|
159
|
-
|
160
175
|
value
|
161
176
|
end
|
162
177
|
|
data/lib/openapi_first/router.rb
CHANGED
@@ -10,11 +10,13 @@ module OpenapiFirst
|
|
10
10
|
app,
|
11
11
|
spec:,
|
12
12
|
raise_error: false,
|
13
|
+
not_found: :halt,
|
13
14
|
parent_app: nil
|
14
15
|
)
|
15
16
|
@app = app
|
16
17
|
@parent_app = parent_app
|
17
18
|
@raise = raise_error
|
19
|
+
@not_found = not_found
|
18
20
|
@filepath = spec.filepath
|
19
21
|
@router = build_router(spec.operations)
|
20
22
|
end
|
@@ -23,9 +25,11 @@ module OpenapiFirst
|
|
23
25
|
env[OPERATION] = nil
|
24
26
|
response = call_router(env)
|
25
27
|
if env[OPERATION].nil?
|
26
|
-
return @parent_app.call(env) if @parent_app # This should only happen if used via OpenapiFirst.
|
28
|
+
return @parent_app.call(env) if @parent_app # This should only happen if used via OpenapiFirst.middleware
|
27
29
|
|
28
30
|
raise_error(env) if @raise
|
31
|
+
|
32
|
+
return @app.call(env) if @not_found == :continue
|
29
33
|
end
|
30
34
|
response
|
31
35
|
end
|
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.
|
4
|
+
version: 0.13.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andreas Haller
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deep_merge
|