esplanade 1.2.1 → 1.7.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
- SHA1:
3
- metadata.gz: 85995e3ffde40ae8fb299e8bdc4ac1173283590c
4
- data.tar.gz: 0f1242bec48b135345a4b6d1680cd6f4fc98f698
2
+ SHA256:
3
+ metadata.gz: 8c136a3d8b6813e9a5be58f5cd21ed11014290ba75aa609fe9d8ba2444326a5d
4
+ data.tar.gz: 5e38971b73680f6e33274360b52343ff459eee5910f9bb16b564751ff45e6a03
5
5
  SHA512:
6
- metadata.gz: d332f111d4860bd09e341c2c8aebfb35157e1582b6506b70d8176ef9ad118b101f14ca6f8aa98898ef95ec0394ae2be2aae9ef9a433bee86411c0367a2f93f82
7
- data.tar.gz: e8d29d45efa8908f74c2f1046c61840131a816218ebd222c618edadaca5a45dedac020a319c56625dbac9aa75140054cf30b6197d97e8602d21db14f991f05e5
6
+ metadata.gz: 21f291d6c57c8ef46908f9844e6fc01bc1d28590cc9817c61947fcc37309c2fca318b2d1a2a8a3756f5175c93677c2a1ef32ab0aba7f385950db505655cf36b0
7
+ data.tar.gz: 2e0384d3a06fc34cf2ba17162bfa447af7a0f35775b9fc50e0c645680b7c7da1277538a48e73dc8c3b0ff0e3ecefeba65470cdcd23383beb7832b13aa6aeaa39
@@ -0,0 +1,33 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ master ]
13
+ pull_request:
14
+ branches: [ master ]
15
+
16
+ jobs:
17
+ test:
18
+
19
+ runs-on: ubuntu-latest
20
+
21
+ steps:
22
+ - uses: actions/checkout@v2
23
+ - name: Set up Ruby
24
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
25
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
26
+ uses: ruby/setup-ruby@v1
27
+ # uses: ruby/setup-ruby@ec106b438a1ff6ff109590de34ddc62c540232e0
28
+ with:
29
+ ruby-version: 2.7
30
+ - name: Install dependencies
31
+ run: bundle install
32
+ - name: Run tests
33
+ run: bundle exec rake
@@ -1,8 +1,9 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.2
2
+ NewCops: enable
3
+ TargetRubyVersion: 2.4
3
4
 
4
- Metrics/LineLength:
5
- Max: 120
5
+ Layout/LineLength:
6
+ Enabled: false
6
7
 
7
8
  Style/Documentation:
8
9
  Enabled: false
@@ -13,6 +14,12 @@ Style/FrozenStringLiteralComment:
13
14
  Metrics/BlockLength:
14
15
  Enabled: false
15
16
 
17
+ Metrics/ParameterLists:
18
+ Enabled: false
19
+
20
+ Metrics/MethodLength:
21
+ Enabled: false
22
+
16
23
  Style/IfUnlessModifier:
17
24
  Enabled: false
18
25
 
@@ -1 +1 @@
1
- 2.2.0
1
+ 2.7.1
@@ -0,0 +1 @@
1
+ ruby 2.7.1
@@ -1,8 +1,39 @@
1
1
  # Change log
2
2
 
3
+ ### 1.7.0 - 2020-12-22
4
+
5
+ * improvements
6
+ * changed middleware arguments
7
+
8
+ ### 1.6.0 - 2020-10-12
9
+
10
+ * features
11
+ * in the errors write not only a documented path but also a raw [#11](https://github.com/funbox/esplanade/issues/11)
12
+ * write in the documentation that the body is empty and nil is skipped [#13](https://github.com/funbox/esplanade/issues/13)
13
+ * redefine error PrefixNotMatch for response [#17](https://github.com/funbox/esplanade/issues/17)
14
+ * content-type can contain additional parameters [#21](https://github.com/funbox/esplanade/issues/21)
15
+ * update esplanade for the new tomograph [#29](https://github.com/funbox/esplanade/issues/29)
16
+
17
+ ### 1.5.0 - 2020-04-07
18
+
19
+ * improvements
20
+ * updated dependenses
21
+ * fixed warnings on ruby 2.7
22
+
23
+ ### 1.4.0 - 2019-08-19
24
+
25
+ * features
26
+ * add details for Esplanade::Response::Error
27
+
28
+ ### 1.3.0 - 2018-03-16
29
+
30
+ * features
31
+ * add Esplanade::Request::ContentTypeIsNotJson error
32
+ * add reduced version message about request body
33
+
3
34
  ### 1.2.1 - 2018-02-20
4
35
 
5
- * improvement
36
+ * features
6
37
  * more information about the invalid request
7
38
 
8
39
  ### 1.2.0 - 2018-02-15
@@ -16,12 +47,12 @@
16
47
 
17
48
  ### 1.1.2 - 2018-02-14
18
49
 
19
- * bug fixes
50
+ * fixes
20
51
  * add rewind rack.input
21
52
 
22
53
  ### 1.1.1 - 2018-02-13
23
54
 
24
- * bug fixes
55
+ * fixes
25
56
  * read body if Content-Type application/json
26
57
 
27
58
  ### 1.1.0 - 2017-10-18
@@ -31,5 +62,5 @@
31
62
 
32
63
  ### 1.0.1 - 2017-10-09
33
64
 
34
- * bug fixes
65
+ * fixes
35
66
  * allow request body to be nil
data/README.md CHANGED
@@ -1,16 +1,36 @@
1
1
  # Esplanade
2
2
 
3
- <a href="https://funbox.ru">
4
- <img src="https://funbox.ru/badges/sponsored_by_funbox.svg" alt="Sponsored by FunBox" width=250 />
5
- </a>
6
-
7
3
  [![Gem Version](https://badge.fury.io/rb/esplanade.svg)](https://badge.fury.io/rb/esplanade)
8
- [![Build Status](https://travis-ci.org/funbox/esplanade.svg?branch=master)](https://travis-ci.org/funbox/esplanade)
9
4
 
10
- This gem will help you validation and sinhronize your API in strict accordance to the documentation in
5
+ This gem helps you to validate and synchronize your API in strict accordance to the documentation in
11
6
  [API Blueprint](https://apiblueprint.org/) format.
12
- To do this it automatically searches received requestes and responses in the documentation and run validates
13
- json-schemas.
7
+ To do this it automatically searches received requests and responses in the documentation and run
8
+ JSON-schemas validators.
9
+
10
+ ## Contents
11
+
12
+ - [Installation](#installation)
13
+ - [Usage](#usage)
14
+ - [Middlewares](#middlewares)
15
+ - [Esplanade::SafeMiddleware](#esplanadesafemiddleware)
16
+ - [Esplanade::DangerousMiddleware](#esplanadedangerousmiddleware)
17
+ - [Esplanade::CheckCustomResponseMiddleware](#esplanadecheckcustomresponsemiddleware)
18
+ - [Esplanade::Error](#esplanadeerror)
19
+ - [Esplanade::Request::Error](#esplanaderequesterror)
20
+ - [Esplanade::Request::PrefixNotMatch](#esplanaderequestprefixnotmatch)
21
+ - [Esplanade::Request::NotDocumented](#esplanaderequestnotdocumented)
22
+ - [Esplanade::Request::ContentTypeIsNotJson](#esplanaderequestcontenttypeisnotjson)
23
+ - [Esplanade::Request::BodyIsNotJson](#esplanaderequestbodyisnotjson)
24
+ - [Esplanade::Request::Invalid](#esplanaderequestinvalid)
25
+ - [Esplanade::Response::Error](#esplanaderesponseerror)
26
+ - [Esplanade::Response::NotDocumented](#esplanaderesponsenotdocumented)
27
+ - [Esplanade::Response::BodyIsNotJson](#esplanaderesponsebodyisnotjson)
28
+ - [Esplanade::Response::Invalid](#esplanaderesponseinvalid)
29
+ - [Middleware args](#middleware-args)
30
+ - [`apib_path`](#apib_path)
31
+ - [`drafter_yaml_path`](#drafter_yaml_path)
32
+ - [`prefix`](#prefix)
33
+ - [License](#license)
14
34
 
15
35
  ## Installation
16
36
 
@@ -20,105 +40,203 @@ Add this line to your application's Gemfile:
20
40
  gem 'esplanade'
21
41
  ```
22
42
 
23
- And then execute:
43
+ After that execute:
24
44
 
25
- $ bundle
45
+ ```bash
46
+ $ bundle
47
+ ```
26
48
 
27
- Or install it yourself as:
49
+ Or install the gem by yourself:
28
50
 
29
- $ gem install esplanade
51
+ ```bash
52
+ $ gem install esplanade
53
+ ```
30
54
 
31
55
  ## Usage
32
56
 
33
- `config/application.rb`
57
+ `config/application.rb`:
34
58
 
35
59
  ```ruby
36
- config.middleware.use Esplanade::SafeMiddleware, apib_path: 'doc.apib'
60
+ config.middleware.use Esplanade::SafeMiddleware, drafter_yaml_path: 'doc.yaml'
37
61
  ```
38
62
 
39
- ## Middleware
63
+ ## Middlewares
40
64
 
41
65
  ### Esplanade::SafeMiddleware
42
66
 
43
- Only debug logger.
67
+ Debug logger.
44
68
 
45
69
  ### Esplanade::DangerousMiddleware
46
70
 
47
- It throws errors, so you will need to add your own middleware for processing.
71
+ It throws errors, so you should add your own middleware for processing.
48
72
 
49
73
  ```ruby
50
- config.middleware.use YourMiddleware
51
- config.middleware.use Esplanade::DangerousMiddleware, apib_path: 'doc.apib'
74
+ config.middleware.use YourMiddleware
75
+ config.middleware.use Esplanade::DangerousMiddleware, drafter_yaml_path: 'doc.yaml'
52
76
  ```
53
77
 
54
78
  ### Esplanade::CheckCustomResponseMiddleware
55
79
 
56
- If you want to be sure that you have documented new custom responses.
80
+ Use it if you want to be sure that you have documented new custom responses.
57
81
 
58
82
  ```ruby
59
- config.middleware.use Esplanade::CheckCustomResponseMiddleware, apib_path: 'doc.apib'
60
- config.middleware.use YourMiddleware
61
- config.middleware.use Esplanade::DangerousMiddleware, apib_path: 'doc.apib'
83
+ config.middleware.use Esplanade::CheckCustomResponseMiddleware, drafter_yaml_path: 'doc.yaml'
84
+ config.middleware.use YourMiddleware
85
+ config.middleware.use Esplanade::DangerousMiddleware, drafter_yaml_path: 'doc.yaml'
62
86
  ```
63
87
 
64
88
  ## Esplanade::Error
65
89
 
66
- From him the `Esplanade::Request::Error` and `Esplanade::Response::Error` are inherited.
90
+ Parent class for those described below.
67
91
 
68
92
  ### Esplanade::Request::Error
69
93
 
70
- From him the `Esplanade::Request::PrefixNotMatch`, `Esplanade::Request::NotDocumented`, `Esplanade::Request::BodyIsNotJson` and `Esplanade::Request::Invalid` are inherited.
94
+ Parent class for those described below. Inherited from `Esplanade::Error`.
71
95
 
72
96
  #### Esplanade::Request::PrefixNotMatch
73
97
 
74
- Error message: `{:method=>"method", :path=>"path"}`.
98
+ Error message format:
99
+
100
+ ```ruby
101
+ {
102
+ :method => "method",
103
+ :path => "path",
104
+ :raw_path => "path",
105
+ :content_type => "content_type"
106
+ }
107
+ ```
75
108
 
76
109
  #### Esplanade::Request::NotDocumented
77
110
 
78
- Error message: `{:method=>"method", :path=>"path"}`.
111
+ Error message format:
112
+
113
+ ```ruby
114
+ {
115
+ :method => "method",
116
+ :path => "path",
117
+ :raw_path => "path",
118
+ :content_type => "content_type"
119
+ }
120
+ ```
121
+
122
+ #### Esplanade::Request::ContentTypeIsNotJson
123
+
124
+ Error message format:
125
+
126
+ ```ruby
127
+ {
128
+ :method => "method",
129
+ :path => "path",
130
+ :raw_path => "path",
131
+ :content_type => "content_type"
132
+ }
133
+ ```
79
134
 
80
135
  #### Esplanade::Request::BodyIsNotJson
81
136
 
82
- Only if the documentation for this request indicates that `Content-Type: application/json`.
137
+ Throws an error also when the body is empty and equal nil.
83
138
 
84
- Error message: `{:method=>"method", :path=>"path", :body=>"{\"state\": 1"}`.
139
+ Error message format:
140
+
141
+ ```ruby
142
+ {
143
+ :method => "method",
144
+ :path => "path",
145
+ :raw_path => "path",
146
+ :content_type => "content_type",
147
+ :body => "body"
148
+ }
149
+ ```
85
150
 
86
151
  #### Esplanade::Request::Invalid
87
152
 
88
- Error message: `{:method=>"method", :path=>"path", :body=>"body", :error=>["error"]}`.
153
+ Error message format:
154
+
155
+ ```ruby
156
+ {
157
+ :method => "method",
158
+ :path => "path",
159
+ :raw_path => "path",
160
+ :content_type => "content_type",
161
+ :body => "body",
162
+ :error => ["error"]
163
+ }
164
+ ```
89
165
 
90
166
  ### Esplanade::Response::Error
91
167
 
92
- From him the `Esplanade::Response::NotDocumented`, `Esplanade::Response::BodyIsNotJson` and `Esplanade::Response::Invalid` are inherited.
168
+ Parent class for those described below. Inherited from `Esplanade::Error`.
93
169
 
94
- #### Esplanade::Response::NotDocumented
170
+ #### Esplanade::Response::PrefixNotMatch
95
171
 
96
- Error message: `{:request=>{:method=>"method", :path=>"path"}, :status=>"status"}`.
172
+ Error message format:
97
173
 
98
- #### Esplanade::Response::BodyIsNotJson
174
+ ```ruby
175
+ {
176
+ :request => {
177
+ :method => "method",
178
+ :path => "path"
179
+ },
180
+ :status => "status"
181
+ }
182
+ ```
99
183
 
100
- Only if the documentation for all the responses of one request indicates that `Content-Type: application/json`.
184
+ #### Esplanade::Response::NotDocumented
101
185
 
102
- Error message: `{:request=>{:method=>"method", :path=>"path"}, :status=>"status", :body=>"body"}`.
186
+ Error message format:
103
187
 
104
- #### Esplanade::Response::Invalid
188
+ ```ruby
189
+ {
190
+ :request => {
191
+ :method => "method",
192
+ :path => "path",
193
+ :raw_path => "path"
194
+ },
195
+ :status => "status"
196
+ }
197
+ ```
105
198
 
106
- Error message: `{:request=>{:method=>"method", :path=>"path"}, :status=>"status", :body=>"body", :error=>["error"]}`.
199
+ #### Esplanade::Response::BodyIsNotJson
107
200
 
108
- ## Middleware args
201
+ It's thrown when expected response to request isn't JSON (not `Content-Type: application/json`) and there's no non-JSON responses documented for the endpoint.
109
202
 
110
- ### apib_path
203
+ Error message format:
111
204
 
112
- Path to API Blueprint documentation. There must be an installed [drafter](https://github.com/apiaryio/drafter) to parse it.
205
+ ```ruby
206
+ {
207
+ :request => {
208
+ :method => "method",
209
+ :path => "path",
210
+ :raw_path => "path"
211
+ },
212
+ :status => "status",
213
+ :body => "body"
214
+ }
215
+ ```
113
216
 
114
- ### drafter_yaml_path
217
+ #### Esplanade::Response::Invalid
115
218
 
116
- Path to API Blueprint documentation pre-parsed with `drafter` and saved to a YAML file.
219
+ Error message format:
117
220
 
118
- ### prefix
221
+ ```ruby
222
+ {
223
+ :request => {
224
+ :method => "method",
225
+ :path => "path",
226
+ :raw_path => "path"
227
+ },
228
+ :status => "status",
229
+ :body => "body",
230
+ :error => ["error"]
231
+ }
232
+ ```
233
+
234
+ ## Middleware args
119
235
 
120
- Prefix of API requests. Example: `'/api'`. The prefix is added to the requests in the documentation.
236
+ Support any [tomograph constructor-params](https://github.com/funbox/tomograph/tree/master#constructor-params)
121
237
 
122
238
  ## License
123
239
 
124
240
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
241
+
242
+ [![Sponsored by FunBox](https://funbox.ru/badges/sponsored_by_funbox_centered.svg)](https://funbox.ru)
@@ -1,4 +1,4 @@
1
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
  require 'esplanade/version'
4
4
 
@@ -18,11 +18,11 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.add_runtime_dependency 'json-schema', '~> 2.6', '>= 2.6.2'
20
20
  spec.add_runtime_dependency 'multi_json', '~> 1.11', '>= 1.11.1'
21
- spec.add_runtime_dependency 'tomograph', '~> 1.2', '>= 1.2.0'
22
- spec.add_development_dependency 'bundler', '~> 1.12'
23
- spec.add_development_dependency 'byebug', '~> 8.2', '>= 8.2.1'
24
- spec.add_development_dependency 'rake', '~> 10.0'
25
- spec.add_development_dependency 'rspec', '~> 3.4', '>= 3.4.0'
26
- spec.add_development_dependency 'rubocop', '~> 0.52', '>= 0.52.1'
27
- spec.add_development_dependency 'simplecov', '~> 0.11', '>= 0.11.2'
21
+ spec.add_runtime_dependency 'tomograph', '~> 3.0.0', '>= 3.0.0'
22
+ spec.add_development_dependency 'byebug', '>= 10.0.0'
23
+ spec.add_development_dependency 'rake', '~> 13'
24
+ spec.add_development_dependency 'rspec', '~> 3.9', '>= 3.9.0'
25
+ spec.add_development_dependency 'rubocop', '~> 0.81', '>= 0.81.0'
26
+ spec.add_development_dependency 'simplecov', '~> 0.18', '>= 0.18'
27
+ spec.required_ruby_version = '>= 2.4.0'
28
28
  end
@@ -1,11 +1,9 @@
1
1
  module Esplanade
2
2
  class Configuration
3
- attr_accessor :apib_path,
4
- :drafter_yaml_path,
5
- :prefix
3
+ attr_accessor :params
6
4
 
7
5
  def initialize
8
- @prefix = ''
6
+ @params = {}
9
7
  end
10
8
  end
11
9
  end
@@ -4,18 +4,9 @@ require 'esplanade/response'
4
4
 
5
5
  module Esplanade
6
6
  class Middleware
7
- def initialize(
8
- app,
9
- prefix: Esplanade.configuration.prefix,
10
- apib_path: Esplanade.configuration.apib_path,
11
- drafter_yaml_path: Esplanade.configuration.drafter_yaml_path
12
- )
7
+ def initialize(app, **params)
13
8
  @app = app
14
- @documentation = Tomograph::Tomogram.new(
15
- prefix: prefix,
16
- apib_path: apib_path,
17
- drafter_yaml_path: drafter_yaml_path
18
- )
9
+ @documentation = Tomograph::Tomogram.new(Esplanade.configuration.params.merge(params))
19
10
  end
20
11
 
21
12
  def call(env)
@@ -4,18 +4,9 @@ require 'esplanade/response'
4
4
 
5
5
  module Esplanade
6
6
  class CheckCustomResponseMiddleware
7
- def initialize(
8
- app,
9
- prefix: Esplanade.configuration.prefix,
10
- apib_path: Esplanade.configuration.apib_path,
11
- drafter_yaml_path: Esplanade.configuration.drafter_yaml_path
12
- )
7
+ def initialize(app, **params)
13
8
  @app = app
14
- @documentation = Tomograph::Tomogram.new(
15
- prefix: prefix,
16
- apib_path: apib_path,
17
- drafter_yaml_path: drafter_yaml_path
18
- )
9
+ @documentation = Tomograph::Tomogram.new(Esplanade.configuration.params.merge(params))
19
10
  end
20
11
 
21
12
  def call(env)
@@ -4,18 +4,9 @@ require 'esplanade/response'
4
4
 
5
5
  module Esplanade
6
6
  class DangerousMiddleware
7
- def initialize(
8
- app,
9
- prefix: Esplanade.configuration.prefix,
10
- apib_path: Esplanade.configuration.apib_path,
11
- drafter_yaml_path: Esplanade.configuration.drafter_yaml_path
12
- )
7
+ def initialize(app, **params)
13
8
  @app = app
14
- @documentation = Tomograph::Tomogram.new(
15
- prefix: prefix,
16
- apib_path: apib_path,
17
- drafter_yaml_path: drafter_yaml_path
18
- )
9
+ @documentation = Tomograph::Tomogram.new(Esplanade.configuration.params.merge(params))
19
10
  end
20
11
 
21
12
  def call(env)
@@ -4,18 +4,9 @@ require 'esplanade/response'
4
4
 
5
5
  module Esplanade
6
6
  class SafeMiddleware
7
- def initialize(
8
- app,
9
- prefix: Esplanade.configuration.prefix,
10
- apib_path: Esplanade.configuration.apib_path,
11
- drafter_yaml_path: Esplanade.configuration.drafter_yaml_path
12
- )
7
+ def initialize(app, **params)
13
8
  @app = app
14
- @documentation = Tomograph::Tomogram.new(
15
- prefix: prefix,
16
- apib_path: apib_path,
17
- drafter_yaml_path: drafter_yaml_path
18
- )
9
+ @documentation = Tomograph::Tomogram.new(Esplanade.configuration.params.merge(params))
19
10
  end
20
11
 
21
12
  def call(env)
@@ -7,14 +7,20 @@ module Esplanade
7
7
  end
8
8
 
9
9
  def tomogram
10
- raise PrefixNotMatch, message unless @main_documentation.prefix_match?(@raw.path)
11
- @tomogram = @main_documentation.find_request(method: @raw.method, path: @raw.path)
12
- raise NotDocumented, message if @tomogram.nil?
10
+ raise PrefixNotMatch.new(**message) unless @main_documentation.prefix_match?(@raw.path)
11
+
12
+ @tomogram = @main_documentation.find_request_with_content_type(
13
+ method: @raw.method,
14
+ path: @raw.path,
15
+ content_type: @raw.content_type
16
+ )
17
+ raise NotDocumented.new(**message) if @tomogram.nil?
18
+
13
19
  @tomogram
14
20
  end
15
21
 
16
- def json_schema
17
- @json_schema ||= tomogram.request
22
+ def json_schemas
23
+ @json_schemas ||= tomogram.requests
18
24
  end
19
25
 
20
26
  def method
@@ -25,6 +31,10 @@ module Esplanade
25
31
  @path ||= tomogram.path.to_s
26
32
  end
27
33
 
34
+ def content_type
35
+ @content_type ||= tomogram.content_type.to_s
36
+ end
37
+
28
38
  def responses
29
39
  @responses ||= tomogram.responses
30
40
  rescue NotDocumented
@@ -36,7 +46,9 @@ module Esplanade
36
46
  def message
37
47
  {
38
48
  method: @raw.method,
39
- path: @raw.path
49
+ path: @raw.path,
50
+ raw_path: @raw.raw_path,
51
+ content_type: @raw.content_type
40
52
  }
41
53
  end
42
54
  end
@@ -3,17 +3,77 @@ module Esplanade
3
3
  class Error < Esplanade::Error; end
4
4
 
5
5
  class PrefixNotMatch < Error; end
6
- class NotDocumented < Error; end
7
- class BodyIsNotJson < Error; end
8
6
 
9
- class Invalid < Error
10
- attr_reader :method, :path, :body, :error
7
+ class NotDocumented < Error
8
+ def initialize(method:, path:, raw_path:, content_type:)
9
+ @method = method
10
+ @path = path
11
+ @raw_path = raw_path
12
+ @content_type = content_type
13
+
14
+ super(to_hash)
15
+ end
11
16
 
12
- def initialize(method:, path:, body:, error:)
17
+ def to_hash
18
+ {
19
+ method: @method,
20
+ path: @path,
21
+ raw_path: @raw_path,
22
+ content_type: @content_type
23
+ }
24
+ end
25
+ end
26
+
27
+ class ContentTypeIsNotJson < Error
28
+ def initialize(method:, path:, raw_path:, content_type:)
29
+ @method = method
30
+ @raw_path = raw_path
31
+ @path = path
32
+ @content_type = content_type
33
+
34
+ super(to_hash)
35
+ end
36
+
37
+ def to_hash
38
+ {
39
+ method: @method,
40
+ path: @path,
41
+ raw_path: @raw_path,
42
+ content_type: @content_type
43
+ }
44
+ end
45
+ end
46
+
47
+ class BodyIsNotJson < Error
48
+ def initialize(method:, path:, raw_path:, content_type:, body:)
49
+ @method = method
50
+ @path = path
51
+ @raw_path = raw_path
52
+ @content_type = content_type
53
+ @body = body
54
+
55
+ super(to_hash)
56
+ end
57
+
58
+ def to_hash
59
+ {
60
+ method: @method,
61
+ path: @path,
62
+ raw_path: @raw_path,
63
+ content_type: @content_type,
64
+ body: @body
65
+ }
66
+ end
67
+ end
68
+
69
+ class Invalid < Error
70
+ def initialize(method:, path:, raw_path:, content_type:, body:, error:)
13
71
  @method = method
14
- @path = path
15
- @body = body
16
- @error = error
72
+ @path = path
73
+ @raw_path = raw_path
74
+ @content_type = content_type
75
+ @body = body
76
+ @error = error
17
77
 
18
78
  super(to_hash)
19
79
  end
@@ -21,9 +81,11 @@ module Esplanade
21
81
  def to_hash
22
82
  {
23
83
  method: @method,
24
- path: @path,
25
- body: @body,
26
- error: @error
84
+ path: @path,
85
+ raw_path: @raw_path,
86
+ content_type: @content_type,
87
+ body: @body,
88
+ error: @error
27
89
  }
28
90
  end
29
91
  end
@@ -15,9 +15,17 @@ module Esplanade
15
15
  @path ||= @env['PATH_INFO']
16
16
  end
17
17
 
18
+ def raw_path
19
+ @raw_path ||= "#{@env['PATH_INFO']}/#{@env['QUERY_STRING']}"
20
+ end
21
+
18
22
  def body
19
23
  @body ||= Body.new(self, @env)
20
24
  end
25
+
26
+ def content_type
27
+ @content_type ||= @env['CONTENT_TYPE'].to_s.split(';').first
28
+ end
21
29
  end
22
30
  end
23
31
  end
@@ -11,19 +11,24 @@ module Esplanade
11
11
 
12
12
  def to_string
13
13
  return @string if @string
14
+
14
15
  @string = @env['rack.input'].read
15
16
  @env['rack.input'].rewind
16
17
  @string
17
18
  end
18
19
 
19
20
  def to_hash
20
- @hash ||= if to_string.nil?
21
- {}
22
- else
23
- MultiJson.load(to_string)
24
- end
21
+ @hash ||= MultiJson.load(to_string)
25
22
  rescue MultiJson::ParseError
26
- raise BodyIsNotJson, message
23
+ raise BodyIsNotJson.new(**message)
24
+ end
25
+
26
+ def reduced_version
27
+ @reduced_version ||= if to_string && to_string.size >= 1000
28
+ "#{to_string[0..499]}...#{to_string[500..-1]}"
29
+ else
30
+ to_string
31
+ end
27
32
  end
28
33
 
29
34
  private
@@ -32,7 +37,9 @@ module Esplanade
32
37
  {
33
38
  method: @raw_request.method,
34
39
  path: @raw_request.path,
35
- body: to_string
40
+ raw_path: @raw_request.raw_path,
41
+ content_type: @raw_request.content_type,
42
+ body: reduced_version
36
43
  }
37
44
  end
38
45
  end
@@ -10,19 +10,52 @@ module Esplanade
10
10
  end
11
11
 
12
12
  def valid!
13
- @error ||= JSON::Validator.fully_validate(@doc.json_schema, @raw.body.to_hash)
13
+ raise ContentTypeIsNotJson.new(**mini_message) unless @doc.content_type == 'application/json'
14
14
 
15
- raise Invalid, message unless @error.empty?
15
+ @error ||= if @doc.json_schemas.size == 1
16
+ one_json_schema
17
+ else
18
+ more_than_one_json_schema
19
+ end
20
+
21
+ raise Invalid.new(**message) unless @error.empty?
16
22
  end
17
23
 
18
24
  private
19
25
 
26
+ def one_json_schema
27
+ JSON::Validator.fully_validate(@doc.json_schemas.first, @raw.body.to_hash)
28
+ end
29
+
30
+ def more_than_one_json_schema
31
+ main_res = @doc.json_schemas.each do |json_schema|
32
+ res = JSON::Validator.fully_validate(json_schema, @raw.body.to_hash)
33
+ break res if res == []
34
+ end
35
+ if main_res != []
36
+ ['invalid']
37
+ else
38
+ []
39
+ end
40
+ end
41
+
42
+ def mini_message
43
+ {
44
+ method: @doc.method,
45
+ path: @doc.path,
46
+ raw_path: @raw.raw_path,
47
+ content_type: @doc.content_type
48
+ }
49
+ end
50
+
20
51
  def message
21
52
  {
22
53
  method: @raw.method,
23
- path: @raw.path,
24
- body: @raw.body.to_hash,
25
- error: @error
54
+ path: @raw.path,
55
+ raw_path: @raw.raw_path,
56
+ content_type: @raw.content_type,
57
+ body: @raw.body.to_hash,
58
+ error: @error
26
59
  }
27
60
  end
28
61
  end
@@ -1,14 +1,10 @@
1
1
  require 'esplanade/response/doc'
2
2
  require 'esplanade/response/raw'
3
3
  require 'esplanade/response/validation'
4
+ require 'esplanade/response/error'
4
5
 
5
6
  module Esplanade
6
7
  class Response
7
- class Error < Esplanade::Error; end
8
- class NotDocumented < Error; end
9
- class BodyIsNotJson < Error; end
10
- class Invalid < Error; end
11
-
12
8
  attr_reader :request
13
9
 
14
10
  def initialize(request, status, raw_body)
@@ -8,8 +8,11 @@ module Esplanade
8
8
 
9
9
  def tomogram
10
10
  @tomogram ||= @request.doc.responses.find_all { |response| response['status'] == @raw.status }
11
- raise NotDocumented, message if @tomogram == []
11
+ raise NotDocumented.new(**message) if @tomogram == []
12
+
12
13
  @tomogram
14
+ rescue Esplanade::Request::PrefixNotMatch
15
+ raise PrefixNotMatch.new(**message)
13
16
  end
14
17
 
15
18
  def json_schemas
@@ -26,6 +29,7 @@ module Esplanade
26
29
  {
27
30
  request: {
28
31
  method: @request.raw.method,
32
+ raw_path: @request.raw.raw_path,
29
33
  path: @request.raw.path
30
34
  },
31
35
  status: @raw.status
@@ -0,0 +1,82 @@
1
+ module Esplanade
2
+ class Response
3
+ class Error < Esplanade::Error; end
4
+
5
+ class PrefixNotMatch < Error; end
6
+
7
+ class NotDocumented < Error
8
+ def initialize(request:, status:)
9
+ @method = request[:method]
10
+ @path = request[:path]
11
+ @raw_path = request[:raw_path]
12
+ @status = status
13
+
14
+ super(to_hash)
15
+ end
16
+
17
+ def to_hash
18
+ {
19
+ request:
20
+ {
21
+ method: @method,
22
+ path: @path,
23
+ raw_path: @raw_path
24
+ },
25
+ status: @status
26
+ }
27
+ end
28
+ end
29
+
30
+ class BodyIsNotJson < Error
31
+ def initialize(request:, status:, body:)
32
+ @method = request[:method]
33
+ @path = request[:path]
34
+ @raw_path = request[:raw_path]
35
+ @status = status
36
+ @body = body
37
+
38
+ super(to_hash)
39
+ end
40
+
41
+ def to_hash
42
+ {
43
+ request:
44
+ {
45
+ method: @method,
46
+ path: @path,
47
+ raw_path: @raw_path
48
+ },
49
+ status: @status,
50
+ body: @body
51
+ }
52
+ end
53
+ end
54
+
55
+ class Invalid < Error
56
+ def initialize(request:, status:, body:, error:)
57
+ @method = request[:method]
58
+ @path = request[:path]
59
+ @raw_path = request[:raw_path]
60
+ @status = status
61
+ @body = body
62
+ @error = error
63
+
64
+ super(to_hash)
65
+ end
66
+
67
+ def to_hash
68
+ {
69
+ request:
70
+ {
71
+ method: @method,
72
+ path: @path,
73
+ raw_path: @raw_path
74
+ },
75
+ status: @status,
76
+ body: @body,
77
+ error: @error
78
+ }
79
+ end
80
+ end
81
+ end
82
+ end
@@ -11,14 +11,14 @@ module Esplanade
11
11
  end
12
12
 
13
13
  def to_string
14
- @string ||= @raw_body.body rescue nil
15
- @string ||= @raw_body.first rescue nil
14
+ @to_string ||= @raw_body.body rescue nil
15
+ @to_string ||= @raw_body.first rescue nil
16
16
  end
17
17
 
18
18
  def to_hash
19
19
  @hash ||= MultiJson.load(to_string)
20
20
  rescue MultiJson::ParseError
21
- raise BodyIsNotJson, message
21
+ raise BodyIsNotJson.new(**message)
22
22
  end
23
23
 
24
24
  private
@@ -27,7 +27,8 @@ module Esplanade
27
27
  {
28
28
  request: {
29
29
  method: @request.raw.method,
30
- path: @request.raw.path
30
+ path: @request.raw.path,
31
+ raw_path: @request.raw.raw_path
31
32
  },
32
33
  status: @raw_response.status,
33
34
  body: @raw_response.body.to_string
@@ -15,7 +15,7 @@ module Esplanade
15
15
  else
16
16
  more_than_one_json_schema
17
17
  end
18
- raise Invalid, message if @error != []
18
+ raise Invalid.new(**message) if @error != []
19
19
  end
20
20
 
21
21
  private
@@ -40,7 +40,8 @@ module Esplanade
40
40
  {
41
41
  request: {
42
42
  method: @request.raw.method,
43
- path: @request.raw.path
43
+ path: @request.raw.path,
44
+ raw_path: @request.raw.raw_path
44
45
  },
45
46
  status: @raw.status,
46
47
  body: @raw.body.to_string,
@@ -1,3 +1,3 @@
1
1
  module Esplanade
2
- VERSION = '1.2.1'.freeze
2
+ VERSION = '1.7.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: esplanade
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - d.efimov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-20 00:00:00.000000000 Z
11
+ date: 2021-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json-schema
@@ -56,128 +56,108 @@ dependencies:
56
56
  requirements:
57
57
  - - "~>"
58
58
  - !ruby/object:Gem::Version
59
- version: '1.2'
59
+ version: 3.0.0
60
60
  - - ">="
61
61
  - !ruby/object:Gem::Version
62
- version: 1.2.0
62
+ version: 3.0.0
63
63
  type: :runtime
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - "~>"
68
68
  - !ruby/object:Gem::Version
69
- version: '1.2'
69
+ version: 3.0.0
70
70
  - - ">="
71
71
  - !ruby/object:Gem::Version
72
- version: 1.2.0
73
- - !ruby/object:Gem::Dependency
74
- name: bundler
75
- requirement: !ruby/object:Gem::Requirement
76
- requirements:
77
- - - "~>"
78
- - !ruby/object:Gem::Version
79
- version: '1.12'
80
- type: :development
81
- prerelease: false
82
- version_requirements: !ruby/object:Gem::Requirement
83
- requirements:
84
- - - "~>"
85
- - !ruby/object:Gem::Version
86
- version: '1.12'
72
+ version: 3.0.0
87
73
  - !ruby/object:Gem::Dependency
88
74
  name: byebug
89
75
  requirement: !ruby/object:Gem::Requirement
90
76
  requirements:
91
- - - "~>"
92
- - !ruby/object:Gem::Version
93
- version: '8.2'
94
77
  - - ">="
95
78
  - !ruby/object:Gem::Version
96
- version: 8.2.1
79
+ version: 10.0.0
97
80
  type: :development
98
81
  prerelease: false
99
82
  version_requirements: !ruby/object:Gem::Requirement
100
83
  requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '8.2'
104
84
  - - ">="
105
85
  - !ruby/object:Gem::Version
106
- version: 8.2.1
86
+ version: 10.0.0
107
87
  - !ruby/object:Gem::Dependency
108
88
  name: rake
109
89
  requirement: !ruby/object:Gem::Requirement
110
90
  requirements:
111
91
  - - "~>"
112
92
  - !ruby/object:Gem::Version
113
- version: '10.0'
93
+ version: '13'
114
94
  type: :development
115
95
  prerelease: false
116
96
  version_requirements: !ruby/object:Gem::Requirement
117
97
  requirements:
118
98
  - - "~>"
119
99
  - !ruby/object:Gem::Version
120
- version: '10.0'
100
+ version: '13'
121
101
  - !ruby/object:Gem::Dependency
122
102
  name: rspec
123
103
  requirement: !ruby/object:Gem::Requirement
124
104
  requirements:
125
105
  - - "~>"
126
106
  - !ruby/object:Gem::Version
127
- version: '3.4'
107
+ version: '3.9'
128
108
  - - ">="
129
109
  - !ruby/object:Gem::Version
130
- version: 3.4.0
110
+ version: 3.9.0
131
111
  type: :development
132
112
  prerelease: false
133
113
  version_requirements: !ruby/object:Gem::Requirement
134
114
  requirements:
135
115
  - - "~>"
136
116
  - !ruby/object:Gem::Version
137
- version: '3.4'
117
+ version: '3.9'
138
118
  - - ">="
139
119
  - !ruby/object:Gem::Version
140
- version: 3.4.0
120
+ version: 3.9.0
141
121
  - !ruby/object:Gem::Dependency
142
122
  name: rubocop
143
123
  requirement: !ruby/object:Gem::Requirement
144
124
  requirements:
145
125
  - - "~>"
146
126
  - !ruby/object:Gem::Version
147
- version: '0.52'
127
+ version: '0.81'
148
128
  - - ">="
149
129
  - !ruby/object:Gem::Version
150
- version: 0.52.1
130
+ version: 0.81.0
151
131
  type: :development
152
132
  prerelease: false
153
133
  version_requirements: !ruby/object:Gem::Requirement
154
134
  requirements:
155
135
  - - "~>"
156
136
  - !ruby/object:Gem::Version
157
- version: '0.52'
137
+ version: '0.81'
158
138
  - - ">="
159
139
  - !ruby/object:Gem::Version
160
- version: 0.52.1
140
+ version: 0.81.0
161
141
  - !ruby/object:Gem::Dependency
162
142
  name: simplecov
163
143
  requirement: !ruby/object:Gem::Requirement
164
144
  requirements:
165
145
  - - "~>"
166
146
  - !ruby/object:Gem::Version
167
- version: '0.11'
147
+ version: '0.18'
168
148
  - - ">="
169
149
  - !ruby/object:Gem::Version
170
- version: 0.11.2
150
+ version: '0.18'
171
151
  type: :development
172
152
  prerelease: false
173
153
  version_requirements: !ruby/object:Gem::Requirement
174
154
  requirements:
175
155
  - - "~>"
176
156
  - !ruby/object:Gem::Version
177
- version: '0.11'
157
+ version: '0.18'
178
158
  - - ">="
179
159
  - !ruby/object:Gem::Version
180
- version: 0.11.2
160
+ version: '0.18'
181
161
  description:
182
162
  email:
183
163
  - d.efimov@fun-box.ru
@@ -185,10 +165,11 @@ executables: []
185
165
  extensions: []
186
166
  extra_rdoc_files: []
187
167
  files:
168
+ - ".github/workflows/ruby.yml"
188
169
  - ".gitignore"
189
170
  - ".rubocop.yml"
190
171
  - ".ruby-version"
191
- - ".travis.yml"
172
+ - ".tool-versions"
192
173
  - CHANGELOG.md
193
174
  - CODE_OF_CONDUCT.md
194
175
  - Gemfile
@@ -213,6 +194,7 @@ files:
213
194
  - lib/esplanade/request/validation.rb
214
195
  - lib/esplanade/response.rb
215
196
  - lib/esplanade/response/doc.rb
197
+ - lib/esplanade/response/error.rb
216
198
  - lib/esplanade/response/raw.rb
217
199
  - lib/esplanade/response/raw/body.rb
218
200
  - lib/esplanade/response/validation.rb
@@ -229,15 +211,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
229
211
  requirements:
230
212
  - - ">="
231
213
  - !ruby/object:Gem::Version
232
- version: '0'
214
+ version: 2.4.0
233
215
  required_rubygems_version: !ruby/object:Gem::Requirement
234
216
  requirements:
235
217
  - - ">="
236
218
  - !ruby/object:Gem::Version
237
219
  version: '0'
238
220
  requirements: []
239
- rubyforge_project:
240
- rubygems_version: 2.4.5
221
+ rubygems_version: 3.1.2
241
222
  signing_key:
242
223
  specification_version: 4
243
224
  summary: Validate requests and responses against API Blueprint specifications
@@ -1,4 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.2
4
- before_install: gem install bundler -v 1.12