openapi_first 1.0.0.beta1 → 1.0.0.beta4
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/.github/workflows/ruby.yml +8 -20
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +23 -0
- data/Gemfile +4 -1
- data/Gemfile.lock +39 -51
- data/README.md +27 -25
- data/benchmarks/Gemfile.lock +28 -33
- data/benchmarks/apps/openapi_first_with_hanami_api.ru +1 -2
- data/benchmarks/apps/openapi_first_with_plain_rack.ru +32 -0
- data/benchmarks/apps/openapi_first_with_response_validation.ru +14 -11
- data/benchmarks/apps/openapi_first_with_sinatra.ru +29 -0
- data/lib/openapi_first/body_parser_middleware.rb +1 -1
- data/lib/openapi_first/config.rb +19 -0
- data/lib/openapi_first/default_error_response.rb +47 -0
- data/lib/openapi_first/definition.rb +8 -1
- data/lib/openapi_first/error_response.rb +31 -0
- data/lib/openapi_first/errors.rb +3 -40
- data/lib/openapi_first/operation.rb +33 -14
- data/lib/openapi_first/operation_schemas.rb +52 -0
- data/lib/openapi_first/plugins.rb +17 -0
- data/lib/openapi_first/request_body_validator.rb +41 -0
- data/lib/openapi_first/request_validation.rb +66 -84
- data/lib/openapi_first/response_validation.rb +38 -7
- data/lib/openapi_first/response_validator.rb +1 -1
- data/lib/openapi_first/router.rb +15 -14
- data/lib/openapi_first/schema_validation.rb +22 -21
- data/lib/openapi_first/string_keyed_hash.rb +20 -0
- data/lib/openapi_first/validation_result.rb +15 -0
- data/lib/openapi_first/version.rb +1 -1
- data/lib/openapi_first.rb +30 -21
- data/openapi_first.gemspec +4 -12
- metadata +20 -117
- data/benchmarks/apps/openapi_first.ru +0 -22
- data/lib/openapi_first/utils.rb +0 -35
- data/lib/openapi_first/validation_format.rb +0 -55
- /data/benchmarks/apps/{committee.ru → committee_with_hanami_api.ru} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c02c053192b6b39cb8f05acd35f7a257ee98b449c49f8ceeec4ac6e542f09e15
|
4
|
+
data.tar.gz: c36d3598b263ebd3d1a9bd23e6aa0b66256890f68e2f70fe245ca932d2f004f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e70192d7c2cb58734b8ebb6ccf53b2f243a98e78adbea271a3b0df1468f400d60080ead1ea68c07dd33bd9985d67de02ec4e0200e3ca0d49272a893c97611ffb
|
7
|
+
data.tar.gz: c59e62cd24dd767330f7e9ce6ad96a9c13005a4498c39f3ccf10bc801b49b6bddccf3ac62f858ae3ecf56fa4c695b4ad010fea7292171f98b640dec968ea357d
|
data/.github/workflows/ruby.yml
CHANGED
@@ -1,24 +1,12 @@
|
|
1
|
-
name:
|
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
|
-
|
11
|
-
|
4
|
+
test:
|
12
5
|
runs-on: ubuntu-latest
|
13
|
-
|
14
6
|
steps:
|
15
|
-
- uses: actions/checkout@
|
16
|
-
-
|
17
|
-
uses: actions/setup-ruby@v1
|
7
|
+
- uses: actions/checkout@v3
|
8
|
+
- uses: ruby/setup-ruby@v1
|
18
9
|
with:
|
19
|
-
ruby-version:
|
20
|
-
|
21
|
-
|
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
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,29 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## Unreleased
|
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
|
+
|
16
|
+
## 1.0.0.beta3
|
17
|
+
|
18
|
+
- Remove obsolete dependency: deep_merge
|
19
|
+
- Remove obsolete dependency: hanami-utils
|
20
|
+
|
21
|
+
## 1.0.0.beta2
|
22
|
+
|
23
|
+
- Fixed dependencies. Remove unused code.
|
24
|
+
|
3
25
|
## 1.0.0.beta1
|
26
|
+
|
4
27
|
- Removed: `OpenapiFirst::Responder` and `OpenapiFirst::RackResponder`
|
5
28
|
- Removed: `OpenapiFirst.app` and `OpenapiFirst.middleware`
|
6
29
|
- Removed: `OpenapiFirst::Coverage`
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,114 +1,102 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
openapi_first (1.0.0.
|
5
|
-
deep_merge (>= 1.2.1)
|
4
|
+
openapi_first (1.0.0.beta4)
|
6
5
|
hanami-router (~> 2.0.0)
|
7
|
-
hanami-utils (~> 2.0.0)
|
8
6
|
json_refs (~> 0.1, >= 0.1.7)
|
9
|
-
json_schemer (~> 0.
|
7
|
+
json_schemer (~> 2.0.0)
|
10
8
|
multi_json (~> 1.14)
|
11
|
-
|
9
|
+
openapi_parameters (~> 0.2.2)
|
12
10
|
rack (>= 2.2, < 4.0)
|
13
11
|
|
14
12
|
GEM
|
15
13
|
remote: https://rubygems.org/
|
16
14
|
specs:
|
17
15
|
ast (2.4.2)
|
18
|
-
|
19
|
-
concurrent-ruby (1.2.2)
|
20
|
-
deep_merge (1.2.2)
|
16
|
+
base64 (0.1.1)
|
21
17
|
diff-lcs (1.5.0)
|
22
|
-
dry-core (1.0.0)
|
23
|
-
concurrent-ruby (~> 1.0)
|
24
|
-
zeitwerk (~> 2.6)
|
25
|
-
dry-transformer (1.0.1)
|
26
|
-
zeitwerk (~> 2.6)
|
27
|
-
ecma-re-validator (0.4.0)
|
28
|
-
regexp_parser (~> 2.2)
|
29
18
|
hana (1.3.7)
|
30
19
|
hanami-router (2.0.2)
|
31
20
|
mustermann (~> 3.0)
|
32
21
|
mustermann-contrib (~> 3.0)
|
33
22
|
rack (~> 2.0)
|
34
|
-
hanami-utils (2.0.3)
|
35
|
-
concurrent-ruby (~> 1.0)
|
36
|
-
dry-core (~> 1.0, < 2)
|
37
|
-
dry-transformer (~> 1.0, < 2)
|
38
23
|
hansi (0.2.1)
|
39
24
|
json (2.6.3)
|
40
|
-
json_refs (0.1.
|
25
|
+
json_refs (0.1.8)
|
41
26
|
hana
|
42
|
-
json_schemer (0.
|
43
|
-
ecma-re-validator (~> 0.3)
|
27
|
+
json_schemer (2.0.0)
|
44
28
|
hana (~> 1.3)
|
45
29
|
regexp_parser (~> 2.0)
|
46
|
-
|
47
|
-
|
30
|
+
simpleidn (~> 0.2)
|
31
|
+
language_server-protocol (3.17.0.3)
|
48
32
|
multi_json (1.15.0)
|
49
33
|
mustermann (3.0.0)
|
50
34
|
ruby2_keywords (~> 0.0.1)
|
51
35
|
mustermann-contrib (3.0.0)
|
52
36
|
hansi (~> 0.2.0)
|
53
37
|
mustermann (= 3.0.0)
|
54
|
-
openapi_parameters (0.2.
|
38
|
+
openapi_parameters (0.2.2)
|
55
39
|
rack (>= 2.2)
|
56
40
|
zeitwerk (~> 2.6)
|
57
|
-
parallel (1.
|
58
|
-
parser (3.2.
|
41
|
+
parallel (1.23.0)
|
42
|
+
parser (3.2.2.3)
|
59
43
|
ast (~> 2.4.1)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
rack (2.
|
64
|
-
|
65
|
-
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)
|
66
49
|
rainbow (3.1.1)
|
67
50
|
rake (13.0.6)
|
68
|
-
regexp_parser (2.
|
69
|
-
rexml (3.2.
|
51
|
+
regexp_parser (2.8.1)
|
52
|
+
rexml (3.2.6)
|
70
53
|
rspec (3.12.0)
|
71
54
|
rspec-core (~> 3.12.0)
|
72
55
|
rspec-expectations (~> 3.12.0)
|
73
56
|
rspec-mocks (~> 3.12.0)
|
74
|
-
rspec-core (3.12.
|
57
|
+
rspec-core (3.12.2)
|
75
58
|
rspec-support (~> 3.12.0)
|
76
|
-
rspec-expectations (3.12.
|
59
|
+
rspec-expectations (3.12.3)
|
77
60
|
diff-lcs (>= 1.2.0, < 2.0)
|
78
61
|
rspec-support (~> 3.12.0)
|
79
|
-
rspec-mocks (3.12.
|
62
|
+
rspec-mocks (3.12.6)
|
80
63
|
diff-lcs (>= 1.2.0, < 2.0)
|
81
64
|
rspec-support (~> 3.12.0)
|
82
|
-
rspec-support (3.12.
|
83
|
-
rubocop (1.
|
65
|
+
rspec-support (3.12.1)
|
66
|
+
rubocop (1.56.3)
|
67
|
+
base64 (~> 0.1.1)
|
84
68
|
json (~> 2.3)
|
69
|
+
language_server-protocol (>= 3.17.0)
|
85
70
|
parallel (~> 1.10)
|
86
|
-
parser (>= 3.2.
|
71
|
+
parser (>= 3.2.2.3)
|
87
72
|
rainbow (>= 2.2.2, < 4.0)
|
88
73
|
regexp_parser (>= 1.8, < 3.0)
|
89
74
|
rexml (>= 3.2.5, < 4.0)
|
90
|
-
rubocop-ast (>= 1.
|
75
|
+
rubocop-ast (>= 1.28.1, < 2.0)
|
91
76
|
ruby-progressbar (~> 1.7)
|
92
77
|
unicode-display_width (>= 2.4.0, < 3.0)
|
93
|
-
rubocop-ast (1.
|
78
|
+
rubocop-ast (1.29.0)
|
94
79
|
parser (>= 3.2.1.0)
|
95
80
|
ruby-progressbar (1.13.0)
|
96
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)
|
97
87
|
unicode-display_width (2.4.2)
|
98
|
-
|
99
|
-
zeitwerk (2.6.7)
|
88
|
+
zeitwerk (2.6.11)
|
100
89
|
|
101
90
|
PLATFORMS
|
102
91
|
arm64-darwin-21
|
92
|
+
x86_64-linux
|
103
93
|
|
104
94
|
DEPENDENCIES
|
105
|
-
bundler
|
95
|
+
bundler
|
106
96
|
openapi_first!
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
rake (~> 13)
|
111
|
-
rspec (~> 3)
|
97
|
+
rack-test
|
98
|
+
rake
|
99
|
+
rspec
|
112
100
|
rubocop
|
113
101
|
|
114
102
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -2,35 +2,37 @@
|
|
2
2
|
|
3
3
|
[](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 [
|
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
|
|
9
|
-
OpenapiFirst
|
9
|
+
- [`OpenapiFirst::RequestValidation`](#request-validation) – Validates the request against the API description and returns 400 if the request is invalid.
|
10
|
+
- [`OpenapiFirst::ResponseValidation`](#response-validation) Validates the response and raises an exception if the response body is invalid.
|
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.
|
10
12
|
|
11
|
-
|
12
|
-
- [`OpenapiFirst::ResponseValidation`](#OpenapiFirst::ResponseValidation) Validates the response and raises an exception if the response body is invalid.
|
13
|
-
- [`OpenapiFirst::Router`](#OpenapiFirst::Router) – This internal middleware is added automatically when using request/response validation. It adds the OpenAPI operation for the current request to the Rack env or returns 404 if no operation was found.
|
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
14
|
|
15
|
-
##
|
15
|
+
## Request Validation
|
16
16
|
|
17
|
-
|
17
|
+
The `OpenapiFirst::RequestValidation` middleware returns a 400 status code with a body that describes the error if the request is not valid.
|
18
18
|
|
19
19
|
```ruby
|
20
20
|
use OpenapiFirst::RequestValidation, spec: 'openapi.yaml'
|
21
21
|
```
|
22
22
|
|
23
|
-
|
24
|
-
|
23
|
+
It adds these fields to the Rack env:
|
24
|
+
|
25
25
|
- `env[OpenapiFirst::PARAMS]` – The parsed parameters (query, path) for the current request (string keyed)
|
26
26
|
- `env[OpenapiFirst::REQUEST_BODY]` – The parsed request body (string keyed)
|
27
|
+
- `env[OpenapiFirst::OPERATION]` (Added via Router) – The Operation object for the current request. This is an instance of `OpenapiFirst::Operation`.
|
27
28
|
|
28
29
|
### Options and defaults
|
29
30
|
|
30
31
|
| Name | Possible values | Description | Default |
|
31
32
|
| :------------- | --------------- | -------------------------------------------------------------------------------------------------- | ---------------------------------- |
|
32
|
-
| `spec:` |
|
33
|
+
| `spec:` | | The path to the spec file or spec loaded via `OpenapiFirst.load` |
|
33
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
|
34
36
|
|
35
37
|
The error responses conform with [JSON:API](https://jsonapi.org).
|
36
38
|
|
@@ -52,8 +54,8 @@ content-type: "application/vnd.api+json"
|
|
52
54
|
}
|
53
55
|
```
|
54
56
|
|
55
|
-
### Parameters
|
56
57
|
|
58
|
+
### Parameters
|
57
59
|
|
58
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:
|
59
61
|
|
@@ -75,9 +77,10 @@ This middleware adds the parsed request body to `env[OpenapiFirst::REQUEST_BODY]
|
|
75
77
|
|
76
78
|
The middleware will return a status `415` if the requests content type does not match or `400` if the request body is invalid.
|
77
79
|
|
78
|
-
### Header, Cookie, Path parameter validation
|
80
|
+
### Header, Cookie, Query and Path parameter validation
|
79
81
|
|
80
|
-
|
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.
|
81
84
|
|
82
85
|
### readOnly / writeOnly properties
|
83
86
|
|
@@ -85,10 +88,9 @@ Request validation fails if request includes a property with `readOnly: true`.
|
|
85
88
|
|
86
89
|
Response validation fails if response body includes a property with `writeOnly: true`.
|
87
90
|
|
88
|
-
##
|
89
|
-
|
90
|
-
This middleware is especially useful when testing. It _always_ raises an error if the response is not valid.
|
91
|
+
## Response validation
|
91
92
|
|
93
|
+
The `OpenapiFirst::ResponseValidation` middleware is especially useful when testing. It _always_ raises an error if the response is not valid.
|
92
94
|
|
93
95
|
```ruby
|
94
96
|
use OpenapiFirst::ResponseValidation, spec: 'openapi.yaml' if ENV['RACK_ENV'] == 'test'
|
@@ -96,25 +98,25 @@ use OpenapiFirst::ResponseValidation, spec: 'openapi.yaml' if ENV['RACK_ENV'] ==
|
|
96
98
|
|
97
99
|
### Options
|
98
100
|
|
99
|
-
| Name
|
100
|
-
|
|
101
|
-
| `spec:`
|
101
|
+
| Name | Possible values | Description | Default |
|
102
|
+
| :------ | --------------- | ---------------------------------------------------------------- | ------- |
|
103
|
+
| `spec:` | | The path to the spec file or spec loaded via `OpenapiFirst.load` |
|
102
104
|
|
103
105
|
## OpenapiFirst::Router
|
104
106
|
|
105
|
-
This middleware is used automatically, but you can add it to the top of your middleware stack if you want to
|
107
|
+
This middleware is used automatically, but you can add it to the top of your middleware stack if you want to customize the behavior via options.
|
106
108
|
|
107
109
|
```ruby
|
108
110
|
use OpenapiFirst::Router, spec: './openapi/openapi.yaml'
|
109
111
|
```
|
110
112
|
|
111
|
-
This middleware adds `env[
|
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).
|
112
114
|
|
113
115
|
### Options and defaults
|
114
116
|
|
115
117
|
| Name | Possible values | Description | Default |
|
116
118
|
| :------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
|
117
|
-
| `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` | |
|
118
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) |
|
119
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) |
|
120
122
|
|
@@ -164,9 +166,9 @@ run OpenapiFirst.app(spec, namespace: Pets)
|
|
164
166
|
|
165
167
|
Run `bin/setup` to install dependencies.
|
166
168
|
|
167
|
-
|
169
|
+
See `bundle exec rake` to run the linter and the tests.
|
168
170
|
|
169
|
-
|
171
|
+
Run `bundle exec rspec` to run the tests only.
|
170
172
|
|
171
173
|
## Benchmarks
|
172
174
|
|
data/benchmarks/Gemfile.lock
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
openapi_first (1.0.0.
|
5
|
-
deep_merge (>= 1.2.1)
|
4
|
+
openapi_first (1.0.0.beta3)
|
6
5
|
hanami-router (~> 2.0.0)
|
7
|
-
hanami-utils (~> 2.0.0)
|
8
6
|
json_refs (~> 0.1, >= 0.1.7)
|
9
|
-
json_schemer (~> 0.
|
7
|
+
json_schemer (~> 2.0.0)
|
10
8
|
multi_json (~> 1.14)
|
11
|
-
|
9
|
+
openapi_parameters (~> 0.2.2)
|
12
10
|
rack (>= 2.2, < 4.0)
|
13
11
|
|
14
12
|
GEM
|
15
13
|
remote: https://rubygems.org/
|
16
14
|
specs:
|
17
|
-
activesupport (7.0.
|
15
|
+
activesupport (7.0.8)
|
18
16
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
19
17
|
i18n (>= 1.6, < 2)
|
20
18
|
minitest (>= 5.1)
|
@@ -28,7 +26,6 @@ GEM
|
|
28
26
|
openapi_parser (~> 1.0)
|
29
27
|
rack (>= 1.5)
|
30
28
|
concurrent-ruby (1.2.2)
|
31
|
-
deep_merge (1.2.2)
|
32
29
|
dry-core (1.0.0)
|
33
30
|
concurrent-ruby (~> 1.0)
|
34
31
|
zeitwerk (~> 2.6)
|
@@ -37,22 +34,18 @@ GEM
|
|
37
34
|
concurrent-ruby (~> 1.0)
|
38
35
|
dry-core (~> 1.0, < 2)
|
39
36
|
zeitwerk (~> 2.6)
|
40
|
-
dry-transformer (1.0.1)
|
41
|
-
zeitwerk (~> 2.6)
|
42
37
|
dry-types (1.7.1)
|
43
38
|
concurrent-ruby (~> 1.0)
|
44
39
|
dry-core (~> 1.0)
|
45
40
|
dry-inflector (~> 1.0)
|
46
41
|
dry-logic (~> 1.4)
|
47
42
|
zeitwerk (~> 2.6)
|
48
|
-
|
49
|
-
regexp_parser (~> 2.2)
|
50
|
-
grape (1.7.0)
|
43
|
+
grape (1.7.1)
|
51
44
|
activesupport
|
52
45
|
builder
|
53
46
|
dry-types (>= 1.1)
|
54
47
|
mustermann-grape (~> 1.0.0)
|
55
|
-
rack (>= 1.3.0)
|
48
|
+
rack (>= 1.3.0, < 3)
|
56
49
|
rack-accept
|
57
50
|
hana (1.3.7)
|
58
51
|
hanami-api (0.3.0)
|
@@ -61,23 +54,18 @@ GEM
|
|
61
54
|
mustermann (~> 3.0)
|
62
55
|
mustermann-contrib (~> 3.0)
|
63
56
|
rack (~> 2.0)
|
64
|
-
hanami-utils (2.0.3)
|
65
|
-
concurrent-ruby (~> 1.0)
|
66
|
-
dry-core (~> 1.0, < 2)
|
67
|
-
dry-transformer (~> 1.0, < 2)
|
68
57
|
hansi (0.2.1)
|
69
|
-
i18n (1.
|
58
|
+
i18n (1.14.1)
|
70
59
|
concurrent-ruby (~> 1.0)
|
71
|
-
json_refs (0.1.
|
60
|
+
json_refs (0.1.8)
|
72
61
|
hana
|
73
62
|
json_schema (0.21.0)
|
74
|
-
json_schemer (0.
|
75
|
-
ecma-re-validator (~> 0.3)
|
63
|
+
json_schemer (2.0.0)
|
76
64
|
hana (~> 1.3)
|
77
65
|
regexp_parser (~> 2.0)
|
78
|
-
|
66
|
+
simpleidn (~> 0.2)
|
79
67
|
memory_profiler (1.0.1)
|
80
|
-
minitest (5.
|
68
|
+
minitest (5.20.0)
|
81
69
|
multi_json (1.15.0)
|
82
70
|
mustermann (3.0.0)
|
83
71
|
ruby2_keywords (~> 0.0.1)
|
@@ -86,24 +74,29 @@ GEM
|
|
86
74
|
mustermann (= 3.0.0)
|
87
75
|
mustermann-grape (1.0.2)
|
88
76
|
mustermann (>= 1.0.0)
|
89
|
-
nio4r (2.5.
|
77
|
+
nio4r (2.5.9)
|
78
|
+
openapi_parameters (0.2.2)
|
79
|
+
rack (>= 2.2)
|
80
|
+
zeitwerk (~> 2.6)
|
90
81
|
openapi_parser (1.0.0)
|
91
|
-
puma (6.
|
82
|
+
puma (6.3.1)
|
92
83
|
nio4r (~> 2.0)
|
93
|
-
rack (2.2.
|
84
|
+
rack (2.2.8)
|
94
85
|
rack-accept (0.4.5)
|
95
86
|
rack (>= 0.4)
|
96
|
-
rack-protection (3.0.
|
87
|
+
rack-protection (3.0.6)
|
97
88
|
rack
|
98
|
-
regexp_parser (2.8.
|
99
|
-
roda (3.
|
89
|
+
regexp_parser (2.8.1)
|
90
|
+
roda (3.68.0)
|
100
91
|
rack
|
101
92
|
ruby2_keywords (0.0.5)
|
102
93
|
seg (1.2.0)
|
103
|
-
|
94
|
+
simpleidn (0.2.1)
|
95
|
+
unf (~> 0.1.4)
|
96
|
+
sinatra (3.0.6)
|
104
97
|
mustermann (~> 3.0)
|
105
98
|
rack (~> 2.2, >= 2.2.4)
|
106
|
-
rack-protection (= 3.0.
|
99
|
+
rack-protection (= 3.0.6)
|
107
100
|
tilt (~> 2.0)
|
108
101
|
syro (3.2.1)
|
109
102
|
rack (>= 1.6.0)
|
@@ -111,8 +104,10 @@ GEM
|
|
111
104
|
tilt (2.1.0)
|
112
105
|
tzinfo (2.0.6)
|
113
106
|
concurrent-ruby (~> 1.0)
|
114
|
-
|
115
|
-
|
107
|
+
unf (0.1.4)
|
108
|
+
unf_ext
|
109
|
+
unf_ext (0.0.8.2)
|
110
|
+
zeitwerk (2.6.11)
|
116
111
|
|
117
112
|
PLATFORMS
|
118
113
|
arm64-darwin-21
|
@@ -19,7 +19,6 @@ app = Class.new(Hanami::API) do
|
|
19
19
|
end
|
20
20
|
end.new
|
21
21
|
|
22
|
-
use OpenapiFirst::
|
23
|
-
use OpenapiFirst::RequestValidation
|
22
|
+
use OpenapiFirst::RequestValidation, spec: File.absolute_path('./openapi.yaml', __dir__)
|
24
23
|
|
25
24
|
run app
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'multi_json'
|
4
|
+
require 'openapi_first'
|
5
|
+
|
6
|
+
app = Rack::Builder.new do
|
7
|
+
use OpenapiFirst::RequestValidation, spec: File.expand_path('./openapi.yaml', __dir__)
|
8
|
+
|
9
|
+
handlers = {
|
10
|
+
'find_thing' => lambda do |env|
|
11
|
+
params = env[OpenapiFirst::PARAMS]
|
12
|
+
body = MultiJson.dump(hello: 'world', id: params.fetch('id'))
|
13
|
+
[200, { 'Content-Type' => 'application/json' }, [body]]
|
14
|
+
end,
|
15
|
+
'find_things' => lambda do |_env|
|
16
|
+
body = MultiJson.dump(hello: 'world')
|
17
|
+
[200, { 'Content-Type' => 'application/json' }, [body]]
|
18
|
+
end,
|
19
|
+
'create_thing' => lambda do |_env|
|
20
|
+
body = MultiJson.dump(hello: 'world')
|
21
|
+
[201, { 'Content-Type' => 'application/json' }, [body]]
|
22
|
+
end
|
23
|
+
}
|
24
|
+
|
25
|
+
not_found = ->(_env) { [404, {}, []] }
|
26
|
+
|
27
|
+
run(lambda do |env|
|
28
|
+
handlers.fetch(env[OpenapiFirst::OPERATION]&.operation_id, not_found).call(env)
|
29
|
+
end)
|
30
|
+
end
|
31
|
+
|
32
|
+
run app
|
@@ -2,21 +2,24 @@
|
|
2
2
|
|
3
3
|
require 'multi_json'
|
4
4
|
require 'openapi_first'
|
5
|
+
require 'hanami/api'
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
app = Class.new(Hanami::API) do
|
8
|
+
get '/hello/:id' do
|
9
|
+
json(hello: 'world', id: params.fetch(:id))
|
9
10
|
end
|
10
11
|
|
11
|
-
|
12
|
-
[{ hello: 'world' }]
|
12
|
+
get '/hello' do
|
13
|
+
json([{ hello: 'world' }])
|
13
14
|
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
post '/hello' do
|
17
|
+
status 201
|
18
|
+
json(hello: 'world')
|
18
19
|
end
|
19
|
-
end
|
20
|
+
end.new
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
use OpenapiFirst::RequestValidation, spec: File.absolute_path('./openapi.yaml', __dir__)
|
23
|
+
use OpenapiFirst::ResponseValidation
|
24
|
+
|
25
|
+
run app
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'multi_json'
|
4
|
+
require 'openapi_first'
|
5
|
+
require 'sinatra'
|
6
|
+
|
7
|
+
class SinatraWithOpenapiFirstExample < Sinatra::Base
|
8
|
+
set :environment, :production
|
9
|
+
|
10
|
+
get '/hello/:id' do
|
11
|
+
content_type :json
|
12
|
+
MultiJson.dump(hello: 'world', id: params.fetch('id'))
|
13
|
+
end
|
14
|
+
|
15
|
+
get '/hello' do
|
16
|
+
content_type :json
|
17
|
+
MultiJson.dump([{ hello: 'world' }])
|
18
|
+
end
|
19
|
+
|
20
|
+
post '/hello' do
|
21
|
+
content_type :json
|
22
|
+
status 201
|
23
|
+
MultiJson.dump(hello: 'world')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
use OpenapiFirst::RequestValidation, spec: File.absolute_path('./openapi.yaml', __dir__)
|
28
|
+
|
29
|
+
run SinatraWithOpenapiFirstExample
|
@@ -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
|