openapi_first 0.8.0 → 0.9.0

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: 82bb84c8685503083fd1b5ef61e6839c706e2a2152c093af842fe96e9a0004cd
4
- data.tar.gz: 20165b2fcb4f10004cd6ee4cab55eeec912bcac6d8d86255cb08c2f2e9f0e8a6
3
+ metadata.gz: 50a431b59d4568cede6b8a110ada173691c698517231299795ee22fc8f54115a
4
+ data.tar.gz: be49aa45dd7b95ee0ec2149b4ec6476c78a42a0e46204c321e5350368bee2d54
5
5
  SHA512:
6
- metadata.gz: dd403e00cdd880573c10de5949db863afd3791eb3271ef26d227e4dffe9efa9775dbb84847acbc3fd79fbc1630be1dc6e71b0c6e7362a992f6350ab2fadf4b1f
7
- data.tar.gz: 9080c126f4a6083ed3e16bcb7f7fd5503b0efaa6633f40cfce2ce85afae4531f15c845ecb76e0138c9395626ec860a7bc9ac51df29c0d11fb2a4970583b5e86e
6
+ metadata.gz: b6b29dab24a951716e9fb73a7f852a4acd3de577cce82008cd329906ef77d73c4cff182face7adb1d36e9ecb9ea170d1655accb9cdc3bba682a818c3c81000b0
7
+ data.tar.gz: d0ad9c915cb4e637dce9ff4f0e6a8bc35cf705c684f69f38d9abbc8edada4b8aef0d2ba226cfae187f9d80da3a229e0f9493ac78bddb0045206ed816cbfe022e
@@ -1,5 +1,8 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.0
4
+ - Make request validation usable standalone
5
+
3
6
  ## 0.8.0
4
7
  - Add merged parameter and request body available to env at `env[OpenapiFirst::INBOX]` in request validation
5
8
  - Path and query parameters with `type: boolean` now get converted to `true`/`false`
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openapi_first (0.8.0)
4
+ openapi_first (0.9.0)
5
5
  hanami-router (~> 2.0.alpha2)
6
6
  hanami-utils (~> 2.0.alpha1)
7
7
  json_schemer (~> 0.2)
data/README.md CHANGED
@@ -35,27 +35,31 @@ Handler functions (`find_pet`) are called with two arguments:
35
35
  - `params` - Holds the parsed request body, filtered query params and path parameters
36
36
  - `res` - Holds a Rack::Response that you can modify if needed
37
37
  If you want to access to plain Rack env you can call `params.env`.
38
+
39
+ ## Rack middlewares
40
+ OpenapiFirst consists of these Rack middlewares:
38
41
 
39
- ### Handling only certain paths
42
+ - `OpenapiFirst::Router` finds the operation for the current request and finds a handler (if namespace option is given)
43
+ - `OpenapiFirst::RequestValidation` validates the request and returns 400 if it's invalid
44
+ - `OpenapiFirst::OperationResolver` calls the handler
40
45
 
41
- You can filter the URIs that should be handled by pass ing `only` to `OpenapiFirst.load`:
46
+ Instead of using `OpenapiFirst.app` you can use these middlwares by itself.
42
47
 
43
- ```ruby
44
- spec = OpenapiFirst.load './openapi/openapi.yaml', only: '/pets'.method(:==)
45
- run OpenapiFirst.app(spec, namespace: Pets)
46
- ```
47
-
48
- ### Usage as Rack middleware
48
+ ## Usage within your Rack webframework
49
+ If you just want to use the request validation part without any handlers you can use the rack middlewares standalone and don't need to pass a `namespace` option:
49
50
 
50
51
  ```ruby
51
- # Just like the above, except the last line
52
- # ...
53
- run OpenapiFirst.middleware('./openapi/openapi.yaml', namespace: Pets)
52
+ use OpenapiFirst::Router, spec: OpenapiFirst.load('./openapi/openapi.yaml')
53
+ use OpenapiFirst::RequestValidation
54
54
  ```
55
55
 
56
- When using the middleware, all requests that are not part of the API description will be passed to the next app.
56
+ ### Rack env variables
57
+ These variables will available in your rack env:
57
58
 
58
- ### Try it out
59
+ - `env[OpenapiFirst::OPERATION]` - Holds an Operation object that responsed about `operation_id` and `path`. This is useful for introspection.
60
+ - `env[OpenapiFirst::INBOX]`. Holds the (filtered) path and query parameters and the response body.
61
+
62
+ ## Try it out
59
63
 
60
64
  See [examples](examples).
61
65
 
@@ -147,6 +151,24 @@ validator = OpenapiFirst::ResponseValidator.new(spec)
147
151
  expect(validator.validate(last_request, last_response).errors).to be_empty
148
152
  ```
149
153
 
154
+ ## If your API description does not contain all endpoints
155
+
156
+ ```ruby
157
+ run OpenapiFirst.middleware('./openapi/openapi.yaml', namespace: Pets)
158
+ ```
159
+
160
+ Here all requests that are not part of the API description will be passed to the next app.
161
+
162
+ ## Handling only certain paths
163
+
164
+ You can filter the URIs that should be handled by passing `only` to `OpenapiFirst.load`:
165
+
166
+ ```ruby
167
+ spec = OpenapiFirst.load './openapi/openapi.yaml', only: '/pets'.method(:==)
168
+ run OpenapiFirst.app(spec, namespace: Pets)
169
+ ```
170
+
171
+
150
172
  ## Coverage
151
173
 
152
174
  (This is a bit experimental. Please try it out and give feedback.)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- openapi_first (0.8.0)
4
+ openapi_first (0.9.0)
5
5
  hanami-router (~> 2.0.alpha2)
6
6
  hanami-utils (~> 2.0.alpha1)
7
7
  json_schemer (~> 0.2)
@@ -2,11 +2,15 @@
2
2
 
3
3
  require 'openapi_first'
4
4
 
5
- module Example
6
- def self.find_thing(_params, _res)
7
- { hello: 'world' }
5
+ module Web
6
+ module Things
7
+ class Index
8
+ def call(_params, _response)
9
+ { hello: 'world' }
10
+ end
11
+ end
8
12
  end
9
13
  end
10
14
 
11
15
  oas_path = File.absolute_path('./openapi.yaml', __dir__)
12
- App = OpenapiFirst.app(oas_path, namespace: Example)
16
+ App = OpenapiFirst.app(oas_path, namespace: Web)
@@ -12,7 +12,7 @@ tags:
12
12
  paths:
13
13
  /:
14
14
  get:
15
- operationId: find_thing
15
+ operationId: things#index
16
16
  summary: Get metadata from the root of the API
17
17
  tags: ["Metadata"]
18
18
  responses:
@@ -10,7 +10,7 @@ module OpenapiFirst
10
10
 
11
11
  def initialize(app, options)
12
12
  @app = app
13
- @namespace = options.fetch(:namespace)
13
+ @namespace = options.fetch(:namespace, nil)
14
14
  @parent_app = options.fetch(:parent_app, nil)
15
15
  @router = build_router(options.fetch(:spec).operations)
16
16
  end
@@ -74,8 +74,8 @@ module OpenapiFirst
74
74
  warn "operationId is missing in '#{operation.method} #{operation.path}'. I am ignoring this operation." # rubocop:disable Layout/LineLength
75
75
  next
76
76
  end
77
- handler = find_handler(operation.operation_id)
78
- if handler.nil?
77
+ handler = @namespace && find_handler(operation.operation_id)
78
+ if @namespace && handler.nil?
79
79
  warn "#{self.class.name} cannot not find handler for '#{operation.operation_id}' (#{operation.method} #{operation.path}). This operation will be ignored." # rubocop:disable Layout/LineLength
80
80
  next
81
81
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OpenapiFirst
4
- VERSION = '0.8.0'
4
+ VERSION = '0.9.0'
5
5
  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.8.0
4
+ version: 0.9.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: 2020-04-20 00:00:00.000000000 Z
11
+ date: 2020-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hanami-router
@@ -176,7 +176,6 @@ files:
176
176
  - benchmarks/apps/hanami_router.ru
177
177
  - benchmarks/apps/openapi.yaml
178
178
  - benchmarks/apps/openapi_first.ru
179
- - benchmarks/apps/openapi_first_resolve_only.ru
180
179
  - benchmarks/apps/sinatra.ru
181
180
  - benchmarks/apps/syro.ru
182
181
  - benchmarks/benchmarks.rb
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'multi_json'
4
- require 'openapi_first'
5
-
6
- namespace = Module.new do
7
- def self.find_thing(params, _res)
8
- { hello: 'world', id: params.fetch('id') }
9
- end
10
-
11
- def self.find_things(_params, _res)
12
- [{ hello: 'world' }]
13
- end
14
-
15
- def self.create_thing(_params, res)
16
- res.status = 201
17
- { hello: 'world' }
18
- end
19
- end
20
-
21
- spec = OpenapiFirst.load(File.absolute_path('./openapi.yaml', __dir__))
22
- use OpenapiFirst::Router, spec: spec, namespace: namespace
23
- run OpenapiFirst::OperationResolver.new