esplanade 1.2.1 → 1.7.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
- 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