esplanade 1.3.0 → 1.7.1

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: ff2aa7471fbccccd7a52e52ba79faa5c181c3fc9
4
- data.tar.gz: 34d21fc0cb3cf09954ce401805076c206508b9d2
2
+ SHA256:
3
+ metadata.gz: 1709500c684e2cd5fb6c0c86445bd413e46ed575e191f5e1557c85680b3b118b
4
+ data.tar.gz: b7aa44c92516981b0f0433378b6b526e48656198782cd8c7fed0d2147a902249
5
5
  SHA512:
6
- metadata.gz: e4cf2e079c8773cdb0b10241ba8166834ab6b6c03b108273e9b7963efa7d812b8a2a2cc7ba249b7c429fffdb80b0dcf36b5b167665b7fef2e00177568f51a32c
7
- data.tar.gz: 62b6623aa9df749907c7d6dc5e6413103bab3083368cc616140c63b9bb3cd4cdfa596a60c857fef5ab57e40b9e8d7a168a606b421ed8db7c079e640387bc8c7a
6
+ metadata.gz: f4372ec2e97839ea3dee256282954c5a5b8540eaa592afa37ab976ef0dff7da7d49357318e292d7aa834ba27f1593b659cf589d159f1ca6e17c6bae1d13bc053
7
+ data.tar.gz: 3a59d0192b6d4bef73e5c239deb16dff6b4fe96eb4b353d67edbf72b645c4084aac0c5d0175e3482c01368023540166939997219b3cbde2a83b7f295dc554d3f
@@ -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
data/.rubocop.yml CHANGED
@@ -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
 
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.2.0
1
+ 2.7.1
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 2.7.1
data/CHANGELOG.md CHANGED
@@ -1,9 +1,39 @@
1
1
  # Change log
2
2
 
3
+ ### 1.7.1 - 2021-02-10
4
+
5
+ * setting
6
+ * improve gemspec dependency for tomograph
7
+
8
+ ### 1.7.0 - 2020-12-22
9
+
10
+ * improvements
11
+ * changed middleware arguments
12
+
13
+ ### 1.6.0 - 2020-10-12
14
+
15
+ * features
16
+ * in the errors write not only a documented path but also a raw [#11](https://github.com/funbox/esplanade/issues/11)
17
+ * write in the documentation that the body is empty and nil is skipped [#13](https://github.com/funbox/esplanade/issues/13)
18
+ * redefine error PrefixNotMatch for response [#17](https://github.com/funbox/esplanade/issues/17)
19
+ * content-type can contain additional parameters [#21](https://github.com/funbox/esplanade/issues/21)
20
+ * update esplanade for the new tomograph [#29](https://github.com/funbox/esplanade/issues/29)
21
+
22
+ ### 1.5.0 - 2020-04-07
23
+
24
+ * improvements
25
+ * updated dependenses
26
+ * fixed warnings on ruby 2.7
27
+
28
+ ### 1.4.0 - 2019-08-19
29
+
30
+ * features
31
+ * add details for Esplanade::Response::Error
32
+
3
33
  ### 1.3.0 - 2018-03-16
4
34
 
5
35
  * features
6
- * add Esplanade::Request::ContentTypeIsNotJson erro
36
+ * add Esplanade::Request::ContentTypeIsNotJson error
7
37
  * add reduced version message about request body
8
38
 
9
39
  ### 1.2.1 - 2018-02-20
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_compact.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,107 +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", :content_type=>"content_type"}`.
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", :content_type=>"content_type"}`.
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
+ ```
79
121
 
80
122
  #### Esplanade::Request::ContentTypeIsNotJson
81
123
 
82
- Error message: `{:method=>"method", :path=>"path", :content_type=>"content_type"}`.
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
+ ```
83
134
 
84
135
  #### Esplanade::Request::BodyIsNotJson
85
136
 
86
- Error message: `{:method=>"method", :path=>"path", :content_type=>"content_type", :body=>"{\"state\": 1"}`.
137
+ Throws an error also when the body is empty and equal nil.
138
+
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
+ ```
87
150
 
88
151
  #### Esplanade::Request::Invalid
89
152
 
90
- Error message: `{:method=>"method", :path=>"path", :content_type=>"content_type", :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
+ ```
91
165
 
92
166
  ### Esplanade::Response::Error
93
167
 
94
- 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`.
95
169
 
96
- #### Esplanade::Response::NotDocumented
170
+ #### Esplanade::Response::PrefixNotMatch
97
171
 
98
- Error message: `{:request=>{:method=>"method", :path=>"path"}, :status=>"status"}`.
172
+ Error message format:
99
173
 
100
- #### Esplanade::Response::BodyIsNotJson
174
+ ```ruby
175
+ {
176
+ :request => {
177
+ :method => "method",
178
+ :path => "path"
179
+ },
180
+ :status => "status"
181
+ }
182
+ ```
101
183
 
102
- Only if the documentation for all the responses of one request indicates that `Content-Type: application/json`.
184
+ #### Esplanade::Response::NotDocumented
103
185
 
104
- Error message: `{:request=>{:method=>"method", :path=>"path"}, :status=>"status", :body=>"body"}`.
186
+ Error message format:
105
187
 
106
- #### Esplanade::Response::Invalid
188
+ ```ruby
189
+ {
190
+ :request => {
191
+ :method => "method",
192
+ :path => "path",
193
+ :raw_path => "path"
194
+ },
195
+ :status => "status"
196
+ }
197
+ ```
198
+
199
+ #### Esplanade::Response::BodyIsNotJson
107
200
 
108
- Error message: `{:request=>{:method=>"method", :path=>"path"}, :status=>"status", :body=>"body", :error=>["error"]}`.
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
- ## Middleware args
203
+ Error message format:
111
204
 
112
- ### apib_path
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
- Path to API Blueprint documentation. There must be an installed [drafter](https://github.com/apiaryio/drafter) to parse it.
217
+ #### Esplanade::Response::Invalid
115
218
 
116
- ### drafter_yaml_path
219
+ Error message format:
117
220
 
118
- Path to API Blueprint documentation pre-parsed with `drafter` and saved to a YAML file.
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
+ ```
119
233
 
120
- ### prefix
234
+ ## Middleware args
121
235
 
122
- 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)
123
237
 
124
238
  ## License
125
239
 
126
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)
data/esplanade.gemspec CHANGED
@@ -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', '~> 2.0', '>= 2.0.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.1', '>= 3.1.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,18 +7,20 @@ module Esplanade
7
7
  end
8
8
 
9
9
  def tomogram
10
- raise PrefixNotMatch, message unless @main_documentation.prefix_match?(@raw.path)
10
+ raise PrefixNotMatch.new(**message) unless @main_documentation.prefix_match?(@raw.path)
11
+
11
12
  @tomogram = @main_documentation.find_request_with_content_type(
12
13
  method: @raw.method,
13
14
  path: @raw.path,
14
15
  content_type: @raw.content_type
15
16
  )
16
- raise NotDocumented, message if @tomogram.nil?
17
+ raise NotDocumented.new(**message) if @tomogram.nil?
18
+
17
19
  @tomogram
18
20
  end
19
21
 
20
- def json_schema
21
- @json_schema ||= tomogram.request
22
+ def json_schemas
23
+ @json_schemas ||= tomogram.requests
22
24
  end
23
25
 
24
26
  def method
@@ -45,6 +47,7 @@ module Esplanade
45
47
  {
46
48
  method: @raw.method,
47
49
  path: @raw.path,
50
+ raw_path: @raw.raw_path,
48
51
  content_type: @raw.content_type
49
52
  }
50
53
  end
@@ -5,9 +5,10 @@ module Esplanade
5
5
  class PrefixNotMatch < Error; end
6
6
 
7
7
  class NotDocumented < Error
8
- def initialize(method:, path:, content_type:)
8
+ def initialize(method:, path:, raw_path:, content_type:)
9
9
  @method = method
10
10
  @path = path
11
+ @raw_path = raw_path
11
12
  @content_type = content_type
12
13
 
13
14
  super(to_hash)
@@ -17,14 +18,16 @@ module Esplanade
17
18
  {
18
19
  method: @method,
19
20
  path: @path,
21
+ raw_path: @raw_path,
20
22
  content_type: @content_type
21
23
  }
22
24
  end
23
25
  end
24
26
 
25
27
  class ContentTypeIsNotJson < Error
26
- def initialize(method:, path:, content_type:)
28
+ def initialize(method:, path:, raw_path:, content_type:)
27
29
  @method = method
30
+ @raw_path = raw_path
28
31
  @path = path
29
32
  @content_type = content_type
30
33
 
@@ -35,15 +38,17 @@ module Esplanade
35
38
  {
36
39
  method: @method,
37
40
  path: @path,
41
+ raw_path: @raw_path,
38
42
  content_type: @content_type
39
43
  }
40
44
  end
41
45
  end
42
46
 
43
47
  class BodyIsNotJson < Error
44
- def initialize(method:, path:, content_type:, body:)
48
+ def initialize(method:, path:, raw_path:, content_type:, body:)
45
49
  @method = method
46
50
  @path = path
51
+ @raw_path = raw_path
47
52
  @content_type = content_type
48
53
  @body = body
49
54
 
@@ -54,6 +59,7 @@ module Esplanade
54
59
  {
55
60
  method: @method,
56
61
  path: @path,
62
+ raw_path: @raw_path,
57
63
  content_type: @content_type,
58
64
  body: @body
59
65
  }
@@ -61,9 +67,10 @@ module Esplanade
61
67
  end
62
68
 
63
69
  class Invalid < Error
64
- def initialize(method:, path:, content_type:, body:, error:)
70
+ def initialize(method:, path:, raw_path:, content_type:, body:, error:)
65
71
  @method = method
66
72
  @path = path
73
+ @raw_path = raw_path
67
74
  @content_type = content_type
68
75
  @body = body
69
76
  @error = error
@@ -75,6 +82,7 @@ module Esplanade
75
82
  {
76
83
  method: @method,
77
84
  path: @path,
85
+ raw_path: @raw_path,
78
86
  content_type: @content_type,
79
87
  body: @body,
80
88
  error: @error
@@ -15,12 +15,16 @@ 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
21
25
 
22
26
  def content_type
23
- @content_type ||= @env['CONTENT_TYPE']
27
+ @content_type ||= @env['CONTENT_TYPE'].to_s.split(';').first
24
28
  end
25
29
  end
26
30
  end
@@ -11,27 +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)
27
24
  end
28
25
 
29
26
  def reduced_version
30
- @reduced_version ||= if to_string.size >= 1000
31
- "#{to_string[0..499]}...#{to_string[500..-1]}"
32
- else
33
- to_string
34
- end
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
35
32
  end
36
33
 
37
34
  private
@@ -40,6 +37,7 @@ module Esplanade
40
37
  {
41
38
  method: @raw_request.method,
42
39
  path: @raw_request.path,
40
+ raw_path: @raw_request.raw_path,
43
41
  content_type: @raw_request.content_type,
44
42
  body: reduced_version
45
43
  }
@@ -10,18 +10,40 @@ module Esplanade
10
10
  end
11
11
 
12
12
  def valid!
13
- raise ContentTypeIsNotJson, mini_message unless @doc.content_type == 'application/json'
14
- @error ||= JSON::Validator.fully_validate(@doc.json_schema, @raw.body.to_hash)
13
+ raise ContentTypeIsNotJson.new(**mini_message) unless @doc.content_type == 'application/json'
15
14
 
16
- 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?
17
22
  end
18
23
 
19
24
  private
20
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
+
21
42
  def mini_message
22
43
  {
23
44
  method: @doc.method,
24
- path: @doc.path,
45
+ path: @doc.path,
46
+ raw_path: @raw.raw_path,
25
47
  content_type: @doc.content_type
26
48
  }
27
49
  end
@@ -29,10 +51,11 @@ module Esplanade
29
51
  def message
30
52
  {
31
53
  method: @raw.method,
32
- path: @raw.path,
54
+ path: @raw.path,
55
+ raw_path: @raw.raw_path,
33
56
  content_type: @raw.content_type,
34
- body: @raw.body.to_hash,
35
- error: @error
57
+ body: @raw.body.to_hash,
58
+ error: @error
36
59
  }
37
60
  end
38
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.3.0'.freeze
2
+ VERSION = '1.7.1'.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.3.0
4
+ version: 1.7.1
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-03-16 00:00:00.000000000 Z
11
+ date: 2021-02-10 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: '2.0'
59
+ version: '3.1'
60
60
  - - ">="
61
61
  - !ruby/object:Gem::Version
62
- version: 2.0.0
62
+ version: 3.1.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: '2.0'
69
+ version: '3.1'
70
70
  - - ">="
71
71
  - !ruby/object:Gem::Version
72
- version: 2.0.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.1.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
data/.travis.yml DELETED
@@ -1,4 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.2
4
- before_install: gem install bundler -v 1.12