committee 3.2.1 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2af076998ef23743c239df64c5517e3e334422a3523f09e6f8baa4f1a9f1ef77
4
- data.tar.gz: a5ae6eca5d34310a69e1c33ca6f11a807e19316c8fad9123521ecf835cfe091c
3
+ metadata.gz: 0c35304cf9026ae20062ea312cdca6b43af486c4c2e5e7c952b35bbad811ce4e
4
+ data.tar.gz: d9a96cd2c6c15b9de26fb95ef0b4d59216c999f8589329d6ee6b21b41e2511d9
5
5
  SHA512:
6
- metadata.gz: 65e65734251a25cb3a3735081c8a3e2e6973b93d1e14b66261d3978e7dac3ea5a9081fe7a530625cf9407d3ac25bc8941d6bea064d07f546186b6a2ebd043fa6
7
- data.tar.gz: 7dee370a2748aa7b67d1e360e86aacb204d16a5a68d18ac879ececc3633d6d92f5ad9b49ba36ac8851e1a04f2322fec2269b8926f30f061d1524bf284af90848
6
+ metadata.gz: 42ffc889dcc301c9de500417390454f4723bf049f0336b9de92b94fcaa2d67f53a7f5c4c9ad5a3a56bd2e9fff70d06ebe7c7279729c616b45ab33625c2a33572
7
+ data.tar.gz: d3c7ca273497b2eb4444fcdb6eb43f49fed866335d1a627f806586f6755557b8a956b43eb5c9448b7cf19176b9e2a4705c78bf6045dde2e98b19fd55211e0070
@@ -8,17 +8,19 @@ module Committee
8
8
 
9
9
  @error_class = options.fetch(:error_class, Committee::ValidationError)
10
10
  @error_handler = options[:error_handler]
11
+ @ignore_error = options.fetch(:ignore_error, false)
11
12
 
12
13
  @raise = options[:raise]
13
14
  @schema = self.class.get_schema(options)
14
15
 
15
16
  @router = @schema.build_router(options)
17
+ @accept_request_filter = options[:accept_request_filter] || -> (_) { true }
16
18
  end
17
19
 
18
20
  def call(env)
19
21
  request = Rack::Request.new(env)
20
22
 
21
- if @router.includes_request?(request)
23
+ if @router.includes_request?(request) && @accept_request_filter.call(request)
22
24
  handle(request)
23
25
  else
24
26
  @app.call(request.env)
@@ -13,27 +13,25 @@ module Committee
13
13
  end
14
14
 
15
15
  def handle(request)
16
- schema_validator = build_schema_validator(request)
17
- schema_validator.request_validate(request)
18
-
19
- raise Committee::NotFound, "That request method and path combination isn't defined." if !schema_validator.link_exist? && @strict
16
+ begin
17
+ schema_validator = build_schema_validator(request)
18
+ schema_validator.request_validate(request)
19
+
20
+ raise Committee::NotFound, "That request method and path combination isn't defined." if !schema_validator.link_exist? && @strict
21
+ rescue Committee::BadRequest, Committee::InvalidRequest
22
+ handle_exception($!, request.env)
23
+ raise if @raise
24
+ return @error_class.new(400, :bad_request, $!.message).render unless @ignore_error
25
+ rescue Committee::NotFound => e
26
+ raise if @raise
27
+ return @error_class.new(404, :not_found, e.message).render unless @ignore_error
28
+ rescue JSON::ParserError
29
+ handle_exception($!, request.env)
30
+ raise Committee::InvalidRequest if @raise
31
+ return @error_class.new(400, :bad_request, "Request body wasn't valid JSON.").render unless @ignore_error
32
+ end
20
33
 
21
34
  @app.call(request.env)
22
- rescue Committee::BadRequest, Committee::InvalidRequest
23
- handle_exception($!, request.env)
24
- raise if @raise
25
- @error_class.new(400, :bad_request, $!.message).render
26
- rescue Committee::NotFound => e
27
- raise if @raise
28
- @error_class.new(
29
- 404,
30
- :not_found,
31
- e.message
32
- ).render
33
- rescue JSON::ParserError
34
- handle_exception($!, request.env)
35
- raise Committee::InvalidRequest if @raise
36
- @error_class.new(400, :bad_request, "Request body wasn't valid JSON.").render
37
35
  end
38
36
 
39
37
  private
@@ -8,7 +8,6 @@ module Committee
8
8
  def initialize(app, options = {})
9
9
  super
10
10
  @validate_success_only = @schema.validator_option.validate_success_only
11
- @ignore_error = options.fetch(:ignore_error, false)
12
11
  end
13
12
 
14
13
  def handle(request)
@@ -379,6 +379,13 @@ describe Committee::Middleware::RequestValidation do
379
379
  assert_match(/expected integer, but received String: foo/i, last_response.body)
380
380
  end
381
381
 
382
+ it "ignores errors when ignore_error: true" do
383
+ @app = new_rack_app(schema: open_api_3_schema, ignore_error: true)
384
+ get "/characters?limit=foo"
385
+
386
+ assert_equal 200, last_response.status
387
+ end
388
+
382
389
  it "coerce string to integer" do
383
390
  check_parameter_string = lambda { |env|
384
391
  assert env['committee.params']['integer'].is_a?(Integer)
@@ -429,6 +436,22 @@ describe Committee::Middleware::RequestValidation do
429
436
  end
430
437
  end
431
438
 
439
+ describe ':accept_request_filter' do
440
+ [
441
+ { description: 'when not specified, includes everything', accept_request_filter: nil, expected: { status: 400 } },
442
+ { description: 'when predicate matches, performs validation', accept_request_filter: -> (request) { request.path.start_with?('/v1/c') }, expected: { status: 400 } },
443
+ { description: 'when predicate does not match, skips validation', accept_request_filter: -> (request) { request.path.start_with?('/v1/x') }, expected: { status: 200 } },
444
+ ].each do |description:, accept_request_filter:, expected:|
445
+ it description do
446
+ @app = new_rack_app(prefix: '/v1', schema: open_api_3_schema, accept_request_filter: accept_request_filter)
447
+
448
+ post 'v1/characters', JSON.generate(string_post_1: 1)
449
+
450
+ assert_equal expected[:status], last_response.status
451
+ end
452
+ end
453
+ end
454
+
432
455
  private
433
456
 
434
457
  def new_rack_app(options = {})
@@ -296,6 +296,16 @@ describe Committee::Middleware::RequestValidation do
296
296
  assert_match(/invalid request/i, last_response.body)
297
297
  end
298
298
 
299
+ it "ignores errors when ignore_error: true" do
300
+ @app = new_rack_app(schema: hyper_schema, ignore_error: true)
301
+ header "Content-Type", "application/json"
302
+ params = {
303
+ "name" => 1
304
+ }
305
+ post "/apps", JSON.generate(params)
306
+ assert_equal 200, last_response.status
307
+ end
308
+
299
309
  it "calls error_handler (has a arg) when request is invalid" do
300
310
  called_err = nil
301
311
  pr = ->(e) { called_err = e }
@@ -480,6 +490,22 @@ describe Committee::Middleware::RequestValidation do
480
490
  assert_equal 200, last_response.status
481
491
  end
482
492
 
493
+ describe ':accept_request_filter' do
494
+ [
495
+ { description: 'when not specified, includes everything', accept_request_filter: nil, expected: { status: 400 } },
496
+ { description: 'when predicate matches, performs validation', accept_request_filter: -> (request) { request.path.start_with?('/v1/a') }, expected: { status: 400 } },
497
+ { description: 'when predicate does not match, skips validation', accept_request_filter: -> (request) { request.path.start_with?('/v1/x') }, expected: { status: 200 } },
498
+ ].each do |description:, accept_request_filter:, expected:|
499
+ it description do
500
+ @app = new_rack_app(prefix: '/v1', schema: hyper_schema, accept_request_filter: accept_request_filter)
501
+
502
+ post '/v1/apps', '{x:y}'
503
+
504
+ assert_equal expected[:status], last_response.status
505
+ end
506
+ end
507
+ end
508
+
483
509
  private
484
510
 
485
511
  def new_rack_app(options = {})
@@ -100,29 +100,41 @@ describe Committee::Middleware::ResponseValidation do
100
100
  end
101
101
 
102
102
  describe 'check header' do
103
- it 'valid type header' do
104
- @app = new_response_rack({}.to_json, {'x-limit' => 1}, schema: open_api_3_schema, raise: true)
105
-
106
- get "/header"
107
-
108
- assert_equal 200, last_response.status
109
- end
110
-
111
- it 'invalid type header' do
112
- @app = new_response_rack({}.to_json, {'x-limit' => '1'}, schema: open_api_3_schema, raise: true)
113
-
114
- assert_raises(Committee::InvalidResponse) do
115
- get "/header"
103
+ [
104
+ { check_header: true, description: 'valid value', header: { 'integer' => 1 }, expected: { status: 200 } },
105
+ { check_header: true, description: 'missing value', header: { 'integer' => nil }, expected: { error: 'headers/integer/schema does not allow null values' } },
106
+ { check_header: true, description: 'invalid value', header: { 'integer' => 'x' }, expected: { error: 'headers/integer/schema expected integer, but received String: x' } },
107
+
108
+ { check_header: false, description: 'valid value', header: { 'integer' => 1 }, expected: { status: 200 } },
109
+ { check_header: false, description: 'missing value', header: { 'integer' => nil }, expected: { status: 200 } },
110
+ { check_header: false, description: 'invalid value', header: { 'integer' => 'x' }, expected: { status: 200 } },
111
+ ].each do |check_header:, description:, header:, expected:|
112
+ describe "when #{check_header}" do
113
+ %w(get post put patch delete).each do |method|
114
+ describe method do
115
+ describe description do
116
+ if expected[:error].nil?
117
+ it 'should pass' do
118
+ @app = new_response_rack({}.to_json, header, schema: open_api_3_schema, raise: true, check_header: check_header)
119
+
120
+ send(method, "/header")
121
+ assert_equal expected[:status], last_response.status
122
+ end
123
+ else
124
+ it 'should fail' do
125
+ @app = new_response_rack({}.to_json, header, schema: open_api_3_schema, raise: true, check_header: check_header)
126
+
127
+ error = assert_raises(Committee::InvalidResponse) do
128
+ get "/header"
129
+ end
130
+ assert_match(expected[:error], error.message)
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
116
136
  end
117
137
  end
118
-
119
- it 'invalid type but not check' do
120
- @app = new_response_rack({}.to_json, {'x-limit' => '1'}, schema: open_api_3_schema, raise: true, check_header: false)
121
-
122
- get "/header"
123
-
124
- assert_equal 200, last_response.status
125
- end
126
138
  end
127
139
 
128
140
  describe 'validate error option' do
@@ -157,6 +169,22 @@ describe Committee::Middleware::ResponseValidation do
157
169
  end
158
170
  end
159
171
 
172
+ describe ':accept_request_filter' do
173
+ [
174
+ { description: 'when not specified, includes everything', accept_request_filter: nil, expected: { status: 500 } },
175
+ { description: 'when predicate matches, performs validation', accept_request_filter: -> (request) { request.path.start_with?('/v1/c') }, expected: { status: 500 } },
176
+ { description: 'when predicate does not match, skips validation', accept_request_filter: -> (request) { request.path.start_with?('/v1/x') }, expected: { status: 200 } },
177
+ ].each do |description:, accept_request_filter:, expected:|
178
+ it description do
179
+ @app = new_response_rack('not_json', {}, schema: open_api_3_schema, prefix: '/v1', accept_request_filter: accept_request_filter)
180
+
181
+ get 'v1/characters'
182
+
183
+ assert_equal expected[:status], last_response.status
184
+ end
185
+ end
186
+ end
187
+
160
188
  private
161
189
 
162
190
  def new_response_rack(response, headers = {}, options = {}, rack_options = {})
@@ -162,6 +162,22 @@ describe Committee::Middleware::ResponseValidation do
162
162
  assert_match(/valid JSON/i, last_response.body)
163
163
  end
164
164
 
165
+ describe ':accept_request_filter' do
166
+ [
167
+ { description: 'when not specified, includes everything', accept_request_filter: nil, expected: { status: 500 } },
168
+ { description: 'when predicate matches, performs validation', accept_request_filter: -> (request) { request.path.start_with?('/v1/a') }, expected: { status: 500 } },
169
+ { description: 'when predicate does not match, skips validation', accept_request_filter: -> (request) { request.path.start_with?('/v1/x') }, expected: { status: 200 } },
170
+ ].each do |description:, accept_request_filter:, expected:|
171
+ it description do
172
+ @app = new_rack_app('not_json', {}, schema: hyper_schema, prefix: '/v1', accept_request_filter: accept_request_filter)
173
+
174
+ get '/v1/apps'
175
+
176
+ assert_equal expected[:status], last_response.status
177
+ end
178
+ end
179
+ end
180
+
165
181
  private
166
182
 
167
183
  def new_rack_app(response, headers = {}, options = {})
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: committee
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.1
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandur
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-10-13 00:00:00.000000000 Z
13
+ date: 2019-11-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json_schema