esplanade 1.2.0 → 1.6.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: d56ac3bbfdcd35af5878ab7c38ba6192ef4e5957
4
- data.tar.gz: a17fd30d62e0039c6d70389e8f197e1b46a8bf17
2
+ SHA256:
3
+ metadata.gz: f5a2030af1a5071793987d6ee1bab57942a83efd21ae68b6323de133c0667e4b
4
+ data.tar.gz: 2474417384e61677938e602e48657bb8acffaeed13cdbf1593c64c4d97620f42
5
5
  SHA512:
6
- metadata.gz: fcbf87e4765ff6ac1b388e490c03dd9c72f57e062fdd9598e247ad4425e51f1723234142af8e0b89ff8611fe7e45834abbbb7c6c49e7237f23729cbe2b07209e
7
- data.tar.gz: 40d6f05bbc3ac4125d0e26f5ff21d0df8fd96fea36eb86efdb99547d3a16d1decb28feb8e93e86ee0cb0382bd21a1453d94cf77b0131e1974fae5ac1487be652
6
+ metadata.gz: 490ca6b622daf918b964966a523d751744923048a5ea78a7eaea7bb4fee5bd6d4623a8951d5255ba0fae49ac78eeba5bc00b6bff876f05c38d9cec88e706a170
7
+ data.tar.gz: b8bfb543326e2d7789d4a1842c96ae163e1a84ba6b3118ee95b57fe53451a308429dc103f7678b613f081d61e29df9668842e2ef8c9062dcdc139bdfa80a0c65
@@ -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.6
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,5 +1,36 @@
1
1
  # Change log
2
2
 
3
+ ### 1.6.0 - 2020-10-12
4
+
5
+ * features
6
+ * in the errors write not only a documented path but also a raw [#11](https://github.com/funbox/esplanade/issues/11)
7
+ * write in the documentation that the body is empty and nil is skipped [#13](https://github.com/funbox/esplanade/issues/13)
8
+ * redefine error PrefixNotMatch for response [#17](https://github.com/funbox/esplanade/issues/17)
9
+ * content-type can contain additional parameters [#21](https://github.com/funbox/esplanade/issues/21)
10
+ * update esplanade for the new tomograph [#29](https://github.com/funbox/esplanade/issues/29)
11
+
12
+ ### 1.5.0 - 2020-04-07
13
+
14
+ * improvements
15
+ * updated dependenses
16
+ * fixed warnings on ruby 2.7
17
+
18
+ ### 1.4.0 - 2019-08-19
19
+
20
+ * features
21
+ * add details for Esplanade::Response::Error
22
+
23
+ ### 1.3.0 - 2018-03-16
24
+
25
+ * features
26
+ * add Esplanade::Request::ContentTypeIsNotJson error
27
+ * add reduced version message about request body
28
+
29
+ ### 1.2.1 - 2018-02-20
30
+
31
+ * features
32
+ * more information about the invalid request
33
+
3
34
  ### 1.2.0 - 2018-02-15
4
35
 
5
36
  * features
@@ -11,12 +42,12 @@
11
42
 
12
43
  ### 1.1.2 - 2018-02-14
13
44
 
14
- * bug fixes
45
+ * fixes
15
46
  * add rewind rack.input
16
47
 
17
48
  ### 1.1.1 - 2018-02-13
18
49
 
19
- * bug fixes
50
+ * fixes
20
51
  * read body if Content-Type application/json
21
52
 
22
53
  ### 1.1.0 - 2017-10-18
@@ -26,5 +57,5 @@
26
57
 
27
58
  ### 1.0.1 - 2017-10-09
28
59
 
29
- * bug fixes
60
+ * fixes
30
61
  * 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,213 @@ 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
60
  config.middleware.use Esplanade::SafeMiddleware, apib_path: 'doc.apib'
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, apib_path: 'doc.apib'
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, apib_path: 'doc.apib'
84
+ config.middleware.use YourMiddleware
85
+ config.middleware.use Esplanade::DangerousMiddleware, apib_path: 'doc.apib'
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`.
169
+
170
+ #### Esplanade::Response::PrefixNotMatch
171
+
172
+ Error message format:
173
+
174
+ ```ruby
175
+ {
176
+ :request => {
177
+ :method => "method",
178
+ :path => "path"
179
+ },
180
+ :status => "status"
181
+ }
182
+ ```
93
183
 
94
184
  #### Esplanade::Response::NotDocumented
95
185
 
96
- Error message: `{:request=>{:method=>"method", :path=>"path"}, :status=>"status"}`.
186
+ Error message format:
187
+
188
+ ```ruby
189
+ {
190
+ :request => {
191
+ :method => "method",
192
+ :path => "path",
193
+ :raw_path => "path"
194
+ },
195
+ :status => "status"
196
+ }
197
+ ```
97
198
 
98
199
  #### Esplanade::Response::BodyIsNotJson
99
200
 
100
- Only if the documentation for all the responses of one request indicates that `Content-Type: application/json`.
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.
202
+
203
+ Error message format:
101
204
 
102
- Error message: `{:request=>{:method=>"method", :path=>"path"}, :status=>"status", :body=>"body"}`.
205
+ ```ruby
206
+ {
207
+ :request => {
208
+ :method => "method",
209
+ :path => "path",
210
+ :raw_path => "path"
211
+ },
212
+ :status => "status",
213
+ :body => "body"
214
+ }
215
+ ```
103
216
 
104
217
  #### Esplanade::Response::Invalid
105
218
 
106
- Error message: `{:request=>{:method=>"method", :path=>"path"}, :status=>"status", :body=>"body", :error=>["error"]}`.
219
+ Error message format:
220
+
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
+ ```
107
233
 
108
234
  ## Middleware args
109
235
 
110
- ### apib_path
236
+ ### `apib_path`
111
237
 
112
238
  Path to API Blueprint documentation. There must be an installed [drafter](https://github.com/apiaryio/drafter) to parse it.
113
239
 
114
- ### drafter_yaml_path
240
+ ### `drafter_yaml_path`
115
241
 
116
242
  Path to API Blueprint documentation pre-parsed with `drafter` and saved to a YAML file.
117
243
 
118
- ### prefix
244
+ ### `prefix`
119
245
 
120
- Prefix of API requests. Example: `'/api'`. The prefix is added to the requests in the documentation.
246
+ Prefix for API requests. Example: `'/api'`. The prefix is added to the requests in the documentation.
121
247
 
122
248
  ## License
123
249
 
124
250
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
251
+
252
+ [![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
@@ -6,9 +6,9 @@ module Esplanade
6
6
  class CheckCustomResponseMiddleware
7
7
  def initialize(
8
8
  app,
9
- prefix: Esplanade.configuration.prefix,
10
- apib_path: Esplanade.configuration.apib_path,
11
- drafter_yaml_path: Esplanade.configuration.drafter_yaml_path
9
+ prefix: Esplanade.configuration.prefix,
10
+ apib_path: Esplanade.configuration.apib_path,
11
+ drafter_yaml_path: Esplanade.configuration.drafter_yaml_path
12
12
  )
13
13
  @app = app
14
14
  @documentation = Tomograph::Tomogram.new(
@@ -1,15 +1,10 @@
1
1
  require 'esplanade/request/doc'
2
2
  require 'esplanade/request/raw'
3
3
  require 'esplanade/request/validation'
4
+ require 'esplanade/request/error'
4
5
 
5
6
  module Esplanade
6
7
  class Request
7
- class Error < Esplanade::Error; end
8
- class PrefixNotMatch < Error; end
9
- class NotDocumented < Error; end
10
- class BodyIsNotJson < Error; end
11
- class Invalid < Error; end
12
-
13
8
  def initialize(documentation, env)
14
9
  @documentation = documentation
15
10
  @env = 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
@@ -0,0 +1,93 @@
1
+ module Esplanade
2
+ class Request
3
+ class Error < Esplanade::Error; end
4
+
5
+ class PrefixNotMatch < Error; end
6
+
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
16
+
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:)
71
+ @method = method
72
+ @path = path
73
+ @raw_path = raw_path
74
+ @content_type = content_type
75
+ @body = body
76
+ @error = error
77
+
78
+ super(to_hash)
79
+ end
80
+
81
+ def to_hash
82
+ {
83
+ method: @method,
84
+ path: @path,
85
+ raw_path: @raw_path,
86
+ content_type: @content_type,
87
+ body: @body,
88
+ error: @error
89
+ }
90
+ end
91
+ end
92
+ end
93
+ 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,17 +10,51 @@ module Esplanade
10
10
  end
11
11
 
12
12
  def valid!
13
- @error ||= JSON::Validator.fully_validate(@doc.json_schema, @raw.body.to_hash)
14
- raise Invalid, message if @error != []
13
+ raise ContentTypeIsNotJson.new(**mini_message) unless @doc.content_type == 'application/json'
14
+
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?
15
22
  end
16
23
 
17
24
  private
18
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
+
19
51
  def message
20
52
  {
21
53
  method: @raw.method,
22
54
  path: @raw.path,
23
- body: @raw.body.to_string,
55
+ raw_path: @raw.raw_path,
56
+ content_type: @raw.content_type,
57
+ body: @raw.body.to_hash,
24
58
  error: @error
25
59
  }
26
60
  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.0'.freeze
2
+ VERSION = '1.6.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.0
4
+ version: 1.6.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-15 00:00:00.000000000 Z
11
+ date: 2020-10-12 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
@@ -207,11 +188,13 @@ files:
207
188
  - lib/esplanade/middlewares/safe_middleware.rb
208
189
  - lib/esplanade/request.rb
209
190
  - lib/esplanade/request/doc.rb
191
+ - lib/esplanade/request/error.rb
210
192
  - lib/esplanade/request/raw.rb
211
193
  - lib/esplanade/request/raw/body.rb
212
194
  - lib/esplanade/request/validation.rb
213
195
  - lib/esplanade/response.rb
214
196
  - lib/esplanade/response/doc.rb
197
+ - lib/esplanade/response/error.rb
215
198
  - lib/esplanade/response/raw.rb
216
199
  - lib/esplanade/response/raw/body.rb
217
200
  - lib/esplanade/response/validation.rb
@@ -228,15 +211,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
228
211
  requirements:
229
212
  - - ">="
230
213
  - !ruby/object:Gem::Version
231
- version: '0'
214
+ version: 2.4.0
232
215
  required_rubygems_version: !ruby/object:Gem::Requirement
233
216
  requirements:
234
217
  - - ">="
235
218
  - !ruby/object:Gem::Version
236
219
  version: '0'
237
220
  requirements: []
238
- rubyforge_project:
239
- rubygems_version: 2.4.5
221
+ rubygems_version: 3.1.2
240
222
  signing_key:
241
223
  specification_version: 4
242
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