my_api_client 0.14.0 → 0.18.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +99 -53
- data/.dependabot/config.yml +19 -1
- data/.rubocop.yml +5 -1
- data/.rubocop_challenge.yml +5 -0
- data/.rubocop_todo.yml +53 -1
- data/CHANGELOG.md +192 -0
- data/Gemfile +0 -3
- data/Gemfile.lock +60 -56
- data/README.jp.md +159 -24
- data/bin/console +4 -0
- data/example/api_clients/application_api_client.rb +2 -10
- data/example/api_clients/my_pagination_api_client.rb +18 -0
- data/example/api_clients/my_rest_api_client.rb +9 -3
- data/lib/generators/rails/USAGE +1 -1
- data/lib/generators/rails/api_client_generator.rb +6 -0
- data/lib/generators/rails/templates/api_client.rb.erb +1 -1
- data/lib/generators/rails/templates/application_api_client.rb.erb +0 -11
- data/lib/generators/rspec/USAGE +1 -1
- data/lib/generators/rspec/api_client_generator.rb +6 -0
- data/lib/generators/rspec/templates/api_client_spec.rb.erb +23 -16
- data/lib/my_api_client.rb +7 -0
- data/lib/my_api_client/base.rb +4 -2
- data/lib/my_api_client/default_error_handlers.rb +64 -0
- data/lib/my_api_client/error_handling.rb +6 -6
- data/lib/my_api_client/error_handling/generator.rb +23 -7
- data/lib/my_api_client/errors.rb +1 -53
- data/lib/my_api_client/errors/api_limit_error.rb +6 -0
- data/lib/my_api_client/errors/client_error.rb +93 -0
- data/lib/my_api_client/errors/network_error.rb +43 -0
- data/lib/my_api_client/errors/server_error.rb +42 -0
- data/lib/my_api_client/params/params.rb +1 -3
- data/lib/my_api_client/request.rb +29 -34
- data/lib/my_api_client/request/basic.rb +32 -0
- data/lib/my_api_client/request/executor.rb +1 -1
- data/lib/my_api_client/request/pagination.rb +39 -0
- data/lib/my_api_client/version.rb +1 -1
- data/my_api/.ruby-version +1 -1
- data/my_api/Gemfile.lock +86 -86
- data/my_api/README.md +6 -0
- data/my_api/app/controllers/pagination_controller.rb +58 -0
- data/my_api/config/routes.rb +1 -0
- data/my_api/spec/controllers/pagination_controller_spec.rb +73 -0
- data/my_api/spec/controllers/rest_controller_spec.rb +23 -5
- data/my_api/spec/spec_helper.rb +5 -0
- data/my_api_client.gemspec +2 -2
- data/rails_app/rails_5.2/.rspec +3 -0
- data/rails_app/rails_5.2/Gemfile +17 -0
- data/rails_app/rails_5.2/Gemfile.lock +171 -0
- data/rails_app/rails_5.2/README.md +24 -0
- data/rails_app/rails_5.2/Rakefile +8 -0
- data/rails_app/rails_5.2/app/controllers/application_controller.rb +4 -0
- data/rails_app/rails_5.2/app/jobs/application_job.rb +4 -0
- data/rails_app/rails_5.2/bin/bundle +5 -0
- data/rails_app/rails_5.2/bin/rails +6 -0
- data/rails_app/rails_5.2/bin/rake +6 -0
- data/rails_app/rails_5.2/bin/setup +27 -0
- data/rails_app/rails_5.2/bin/update +27 -0
- data/rails_app/rails_5.2/config.ru +7 -0
- data/rails_app/rails_5.2/config/application.rb +37 -0
- data/rails_app/rails_5.2/config/boot.rb +6 -0
- data/rails_app/rails_5.2/config/credentials.yml.enc +1 -0
- data/rails_app/rails_5.2/config/environment.rb +7 -0
- data/rails_app/rails_5.2/config/environments/development.rb +41 -0
- data/rails_app/rails_5.2/config/environments/production.rb +70 -0
- data/rails_app/rails_5.2/config/environments/test.rb +38 -0
- data/rails_app/rails_5.2/config/initializers/application_controller_renderer.rb +9 -0
- data/rails_app/rails_5.2/config/initializers/backtrace_silencers.rb +8 -0
- data/rails_app/rails_5.2/config/initializers/cors.rb +17 -0
- data/rails_app/rails_5.2/config/initializers/filter_parameter_logging.rb +6 -0
- data/rails_app/rails_5.2/config/initializers/inflections.rb +17 -0
- data/rails_app/rails_5.2/config/initializers/mime_types.rb +5 -0
- data/rails_app/rails_5.2/config/initializers/wrap_parameters.rb +11 -0
- data/rails_app/rails_5.2/config/locales/en.yml +33 -0
- data/rails_app/rails_5.2/config/routes.rb +5 -0
- data/rails_app/rails_5.2/config/spring.rb +8 -0
- data/rails_app/rails_5.2/public/robots.txt +1 -0
- data/rails_app/rails_5.2/spec/rails_helper.rb +14 -0
- data/rails_app/rails_5.2/spec/spec_helper.rb +13 -0
- data/rails_app/rails_6.0/.rspec +3 -0
- data/rails_app/rails_6.0/Gemfile +17 -0
- data/rails_app/rails_6.0/Gemfile.lock +186 -0
- data/rails_app/rails_6.0/README.md +24 -0
- data/rails_app/rails_6.0/Rakefile +8 -0
- data/rails_app/rails_6.0/app/controllers/application_controller.rb +4 -0
- data/rails_app/rails_6.0/app/jobs/application_job.rb +9 -0
- data/rails_app/rails_6.0/bin/rails +6 -0
- data/rails_app/rails_6.0/bin/rake +6 -0
- data/rails_app/rails_6.0/bin/setup +27 -0
- data/rails_app/rails_6.0/config.ru +7 -0
- data/rails_app/rails_6.0/config/application.rb +39 -0
- data/rails_app/rails_6.0/config/boot.rb +6 -0
- data/rails_app/rails_6.0/config/credentials.yml.enc +1 -0
- data/rails_app/rails_6.0/config/environment.rb +7 -0
- data/rails_app/rails_6.0/config/environments/development.rb +39 -0
- data/rails_app/rails_6.0/config/environments/production.rb +90 -0
- data/rails_app/rails_6.0/config/environments/test.rb +41 -0
- data/rails_app/rails_6.0/config/initializers/application_controller_renderer.rb +9 -0
- data/rails_app/rails_6.0/config/initializers/backtrace_silencers.rb +8 -0
- data/rails_app/rails_6.0/config/initializers/cors.rb +17 -0
- data/rails_app/rails_6.0/config/initializers/filter_parameter_logging.rb +6 -0
- data/rails_app/rails_6.0/config/initializers/inflections.rb +17 -0
- data/rails_app/rails_6.0/config/initializers/mime_types.rb +5 -0
- data/rails_app/rails_6.0/config/initializers/wrap_parameters.rb +11 -0
- data/rails_app/rails_6.0/config/locales/en.yml +33 -0
- data/rails_app/rails_6.0/config/routes.rb +5 -0
- data/rails_app/rails_6.0/config/spring.rb +8 -0
- data/rails_app/rails_6.0/public/robots.txt +1 -0
- data/rails_app/rails_6.0/spec/rails_helper.rb +14 -0
- data/rails_app/rails_6.0/spec/spec_helper.rb +13 -0
- metadata +81 -8
- data/gemfiles/rails_4.2.gemfile +0 -15
- data/renovate.json +0 -21
data/bin/console
CHANGED
@@ -3,6 +3,10 @@
|
|
3
3
|
|
4
4
|
require 'bundler/setup'
|
5
5
|
require 'my_api_client'
|
6
|
+
require './example/api_clients/my_error_api_client'
|
7
|
+
require './example/api_clients/my_rest_api_client'
|
8
|
+
require './example/api_clients/my_pagination_api_client'
|
9
|
+
require './example/api_clients/my_status_api_client'
|
6
10
|
|
7
11
|
# You can add fixtures and/or initialization code here to make experimenting
|
8
12
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -8,14 +8,6 @@ class ApplicationApiClient < MyApiClient::Base
|
|
8
8
|
|
9
9
|
self.logger = ::Logger.new(nil)
|
10
10
|
|
11
|
-
http_open_timeout
|
12
|
-
http_read_timeout
|
13
|
-
|
14
|
-
retry_on MyApiClient::NetworkError, wait: 0.seconds, attempts: 3
|
15
|
-
|
16
|
-
error_handling status_code: 400..499, raise: MyApiClient::ClientError
|
17
|
-
error_handling status_code: 500..599 do |params, logger|
|
18
|
-
logger.warn 'Server error occurred.'
|
19
|
-
raise MyApiClient::ServerError, params
|
20
|
-
end
|
11
|
+
http_open_timeout 5.seconds
|
12
|
+
http_read_timeout 5.seconds
|
21
13
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'application_api_client'
|
4
|
+
|
5
|
+
# An usage example of the `my_api_client`.
|
6
|
+
# See also: my_api/app/controllers/pagination_controller.rb
|
7
|
+
class MyPaginationApiClient < ApplicationApiClient
|
8
|
+
# GET pagination?page=1
|
9
|
+
def pagination
|
10
|
+
pget 'pagination', paging: '$.links.next', headers: headers, query: { page: 1 }
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def headers
|
16
|
+
{ 'Content-Type': 'application/json;charset=UTF-8' }
|
17
|
+
end
|
18
|
+
end
|
@@ -18,13 +18,19 @@ class MyRestApiClient < ApplicationApiClient
|
|
18
18
|
end
|
19
19
|
|
20
20
|
# POST rest
|
21
|
-
def
|
21
|
+
def post_post(title:)
|
22
22
|
body = { title: title }
|
23
23
|
post 'rest', body: body, headers: headers
|
24
24
|
end
|
25
25
|
|
26
|
-
#
|
27
|
-
def
|
26
|
+
# PUT rest/:id
|
27
|
+
def put_post(id:, title:)
|
28
|
+
body = { title: title }
|
29
|
+
put "rest/#{id}", body: body, headers: headers
|
30
|
+
end
|
31
|
+
|
32
|
+
# PATCH rest/:id
|
33
|
+
def patch_post(id:, title:)
|
28
34
|
body = { title: title }
|
29
35
|
patch "rest/#{id}", body: body, headers: headers
|
30
36
|
end
|
data/lib/generators/rails/USAGE
CHANGED
@@ -2,7 +2,7 @@ Description:
|
|
2
2
|
Generate a new api client class files.
|
3
3
|
|
4
4
|
Example:
|
5
|
-
`rails g api_client path/to/resource get:path/to/resource`
|
5
|
+
`rails g api_client path/to/resource get:path/to/resource` --endpoint https://example.com
|
6
6
|
|
7
7
|
This will create:
|
8
8
|
create app/api_clients/application_api_client.rb
|
@@ -15,6 +15,12 @@ module Rails
|
|
15
15
|
default: %w[get:path/to/resource post:path/to/resource],
|
16
16
|
banner: '{method}:{path} {method}:{path}'
|
17
17
|
|
18
|
+
class_option :endpoint,
|
19
|
+
type: :string,
|
20
|
+
default: 'https://example.com',
|
21
|
+
banner: 'https://example.com',
|
22
|
+
desc: 'Common part of the target API endpoint'
|
23
|
+
|
18
24
|
def generate_root_class
|
19
25
|
file_path = File.join('app/api_clients', 'application_api_client.rb')
|
20
26
|
return if File.exist?(file_path)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class <%= "#{class_name}ApiClient" %> < ::ApplicationApiClient
|
4
|
-
endpoint '
|
4
|
+
endpoint '<%= options[:endpoint] %>'
|
5
5
|
|
6
6
|
# error_handling json: { '$.errors.code': 10 } do |params, logger|
|
7
7
|
# # Behavior when detected an error.
|
@@ -20,15 +20,4 @@ class ApplicationApiClient < MyApiClient::Base
|
|
20
20
|
# seconds.
|
21
21
|
#
|
22
22
|
# http_read_timeout 3.seconds
|
23
|
-
|
24
|
-
# Catch the exception and re-execution after any seconds, like as ActiveJob.
|
25
|
-
# Please note that it is executed as a synchronous process unlike ActiveJob.
|
26
|
-
#
|
27
|
-
# retry_on MyApiClient::NetworkError, wait: 5.seconds, attempts: 3
|
28
|
-
|
29
|
-
# Set a HTTP response verifyment and behavior. If conflicting conditions are
|
30
|
-
# set, the processing defined later takes precedence
|
31
|
-
#
|
32
|
-
# error_handling status_code: 400..499, raise: MyApiClient::ClientError
|
33
|
-
# error_handling status_code: 500..599, raise: MyApiClient::ServerError
|
34
23
|
end
|
data/lib/generators/rspec/USAGE
CHANGED
@@ -2,7 +2,7 @@ Description:
|
|
2
2
|
Generate a new api client spec files.
|
3
3
|
|
4
4
|
Example:
|
5
|
-
rails g rspec:api_client path/to/resource get:path/to/resource`
|
5
|
+
rails g rspec:api_client path/to/resource get:path/to/resource` --endpoint https://example.com
|
6
6
|
|
7
7
|
This will create:
|
8
8
|
create spec/api_clients/path/to/resource_api_client_spec.rb
|
@@ -16,6 +16,12 @@ module Rspec
|
|
16
16
|
default: %w[get:path/to/resource post:path/to/resource],
|
17
17
|
banner: '{method}:{path} {method}:{path}'
|
18
18
|
|
19
|
+
class_option :endpoint,
|
20
|
+
type: :string,
|
21
|
+
default: 'https://example.com',
|
22
|
+
banner: 'https://example.com',
|
23
|
+
desc: 'Common part of the target API endpoint'
|
24
|
+
|
19
25
|
class_option :api_client_specs, type: :boolean, default: true
|
20
26
|
|
21
27
|
def generate_api_client_spec
|
@@ -11,16 +11,28 @@ RSpec.describe <%= "#{class_name}ApiClient" %>, <%= type_metatag(:api_client) %>
|
|
11
11
|
end
|
12
12
|
|
13
13
|
shared_examples 'to handle errors' do
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
context 'when the API returns 200 OK' do
|
15
|
+
it do
|
16
|
+
expect { api_request }
|
17
|
+
.not_to be_handled_as_an_error
|
18
|
+
.when_receive(status_code: 200)
|
19
|
+
end
|
18
20
|
end
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
context 'when the API returns 400 Bad Request' do
|
23
|
+
it do
|
24
|
+
expect { api_request }
|
25
|
+
.to be_handled_as_an_error(MyApiClient::ClientError::BadRequest)
|
26
|
+
.when_receive(status_code: 400)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when the API returns 500 Internal Server Error' do
|
31
|
+
it do
|
32
|
+
expect { api_request }
|
33
|
+
.to be_handled_as_an_error(MyApiClient::ServerError::InternalServerError)
|
34
|
+
.when_receive(status_code: 500)
|
35
|
+
end
|
24
36
|
end
|
25
37
|
end
|
26
38
|
<% yeild_request_arguments do |action, http_method, pathname| -%>
|
@@ -28,22 +40,17 @@ RSpec.describe <%= "#{class_name}ApiClient" %>, <%= type_metatag(:api_client) %>
|
|
28
40
|
describe '#<%= action %>' do
|
29
41
|
subject(:api_request) { api_client.<%= action %> }
|
30
42
|
|
43
|
+
it_behaves_like 'to handle errors'
|
44
|
+
|
31
45
|
it do
|
32
46
|
expect { api_request }
|
33
|
-
.to request_to(:<%= http_method %>, '
|
47
|
+
.to request_to(:<%= http_method %>, '<%= options[:endpoint] %>/<%= pathname %>')
|
34
48
|
<% if http_method == 'get' -%>
|
35
49
|
.with(headers: headers, query: {})
|
36
50
|
<% else -%>
|
37
51
|
.with(headers: headers, body: {})
|
38
52
|
<% end -%>
|
39
53
|
end
|
40
|
-
|
41
|
-
it_behaves_like 'to handle errors' do
|
42
|
-
it do
|
43
|
-
expect { api_request }.not_to be_handled_as_an_error
|
44
|
-
.when_receive(status_code: 200, body: nil, headers: nil)
|
45
|
-
end
|
46
|
-
end
|
47
54
|
end
|
48
55
|
<% end -%>
|
49
56
|
end
|
data/lib/my_api_client.rb
CHANGED
@@ -16,7 +16,14 @@ require 'my_api_client/error_handling'
|
|
16
16
|
require 'my_api_client/exceptions'
|
17
17
|
require 'my_api_client/request/logger'
|
18
18
|
require 'my_api_client/request/executor'
|
19
|
+
require 'my_api_client/request/basic'
|
20
|
+
require 'my_api_client/request/pagination'
|
19
21
|
require 'my_api_client/errors'
|
22
|
+
require 'my_api_client/errors/api_limit_error'
|
23
|
+
require 'my_api_client/errors/client_error'
|
24
|
+
require 'my_api_client/errors/network_error'
|
25
|
+
require 'my_api_client/errors/server_error'
|
26
|
+
require 'my_api_client/default_error_handlers'
|
20
27
|
require 'my_api_client/params/params'
|
21
28
|
require 'my_api_client/params/request'
|
22
29
|
require 'my_api_client/request'
|
data/lib/my_api_client/base.rb
CHANGED
@@ -9,15 +9,17 @@ module MyApiClient
|
|
9
9
|
include MyApiClient::Request
|
10
10
|
|
11
11
|
if ActiveSupport::VERSION::STRING >= '5.2.0'
|
12
|
-
class_attribute :logger, instance_writer: false, default: ::Logger.new(
|
12
|
+
class_attribute :logger, instance_writer: false, default: ::Logger.new($stdout)
|
13
13
|
class_attribute :error_handlers, instance_writer: false, default: []
|
14
14
|
else
|
15
15
|
class_attribute :logger
|
16
16
|
class_attribute :error_handlers
|
17
|
-
self.logger = ::Logger.new(
|
17
|
+
self.logger = ::Logger.new($stdout)
|
18
18
|
self.error_handlers = []
|
19
19
|
end
|
20
20
|
|
21
|
+
include MyApiClient::DefaultErrorHandlers
|
22
|
+
|
21
23
|
# NOTE: This class **MUST NOT** implement #initialize method. Because it
|
22
24
|
# will become constraint that need call #super in the #initialize at
|
23
25
|
# definition of the child classes.
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MyApiClient
|
4
|
+
# Provides default error handlers.
|
5
|
+
module DefaultErrorHandlers
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
# rubocop:disable Metrics/BlockLength
|
9
|
+
included do
|
10
|
+
# NOTE: The built-in error handlers are following. Although they are prepared
|
11
|
+
# to save the trouble of defining, but you can override any error handlers
|
12
|
+
# in your API client class.
|
13
|
+
error_handling status_code: 400..499, raise: ClientError
|
14
|
+
error_handling status_code: 400, raise: ClientError::BadRequest
|
15
|
+
error_handling status_code: 401, raise: ClientError::Unauthorized
|
16
|
+
error_handling status_code: 402, raise: ClientError::PaymentRequired
|
17
|
+
error_handling status_code: 403, raise: ClientError::Forbidden
|
18
|
+
error_handling status_code: 404, raise: ClientError::NotFound
|
19
|
+
error_handling status_code: 405, raise: ClientError::MethodNotAllowed
|
20
|
+
error_handling status_code: 406, raise: ClientError::NotAcceptable
|
21
|
+
error_handling status_code: 407, raise: ClientError::ProxyAuthenticationRequired
|
22
|
+
error_handling status_code: 408, raise: ClientError::RequestTimeout
|
23
|
+
error_handling status_code: 409, raise: ClientError::Conflict
|
24
|
+
error_handling status_code: 410, raise: ClientError::Gone
|
25
|
+
error_handling status_code: 411, raise: ClientError::LengthRequired
|
26
|
+
error_handling status_code: 412, raise: ClientError::PreconditionFailed
|
27
|
+
error_handling status_code: 413, raise: ClientError::RequestEntityTooLarge
|
28
|
+
error_handling status_code: 414, raise: ClientError::RequestUriTooLong
|
29
|
+
error_handling status_code: 415, raise: ClientError::UnsupportedMediaType
|
30
|
+
error_handling status_code: 416, raise: ClientError::RequestedRangeNotSatisfiable
|
31
|
+
error_handling status_code: 417, raise: ClientError::ExpectationFailed
|
32
|
+
error_handling status_code: 418, raise: ClientError::IamTeapot
|
33
|
+
error_handling status_code: 421, raise: ClientError::MisdirectedRequest
|
34
|
+
error_handling status_code: 422, raise: ClientError::UnprocessableEntity
|
35
|
+
error_handling status_code: 423, raise: ClientError::Locked
|
36
|
+
error_handling status_code: 424, raise: ClientError::FailedDependency
|
37
|
+
error_handling status_code: 425, raise: ClientError::TooEarly
|
38
|
+
error_handling status_code: 426, raise: ClientError::UpgradeRequired
|
39
|
+
error_handling status_code: 428, raise: ClientError::PreconditionRequired
|
40
|
+
error_handling status_code: 429, raise: ClientError::TooManyRequests
|
41
|
+
error_handling status_code: 431, raise: ClientError::RequestHeaderFieldsTooLarge
|
42
|
+
error_handling status_code: 451, raise: ClientError::UnavailableForLegalReasons
|
43
|
+
|
44
|
+
error_handling status_code: 500..599, raise: ServerError
|
45
|
+
error_handling status_code: 500, raise: ServerError::InternalServerError
|
46
|
+
error_handling status_code: 501, raise: ServerError::NotImplemented
|
47
|
+
error_handling status_code: 502, raise: ServerError::BadGateway
|
48
|
+
error_handling status_code: 503, raise: ServerError::ServiceUnavailable
|
49
|
+
error_handling status_code: 504, raise: ServerError::GatewayTimeout
|
50
|
+
error_handling status_code: 505, raise: ServerError::HttpVersionNotSupported
|
51
|
+
error_handling status_code: 506, raise: ServerError::VariantAlsoNegotiates
|
52
|
+
error_handling status_code: 507, raise: ServerError::InsufficientStorage
|
53
|
+
error_handling status_code: 508, raise: ServerError::LoopDetected
|
54
|
+
error_handling status_code: 509, raise: ServerError::BandwidthLimitExceeded
|
55
|
+
error_handling status_code: 510, raise: ServerError::NotExtended
|
56
|
+
error_handling status_code: 511, raise: ServerError::NetworkAuthenticationRequired
|
57
|
+
|
58
|
+
# Catch the exception and re-execution after any seconds, like as ActiveJob.
|
59
|
+
# Please note that it is executed as a synchronous process unlike ActiveJob.
|
60
|
+
retry_on NetworkError, wait: 0.3.seconds, attempts: 3
|
61
|
+
end
|
62
|
+
# rubocop:enable Metrics/BlockLength
|
63
|
+
end
|
64
|
+
end
|
@@ -9,9 +9,8 @@ module MyApiClient
|
|
9
9
|
# @example
|
10
10
|
# error_handling status_code: 200, json: :forbid_nil
|
11
11
|
# error_handling status_code: 400..499, raise: MyApiClient::ClientError
|
12
|
-
# error_handling status_code: 500..599 do |params, logger|
|
12
|
+
# error_handling status_code: 500..599, raise: MyApiClient::ServerError do |params, logger|
|
13
13
|
# logger.warn 'Server error occurred.'
|
14
|
-
# raise MyApiClient::ServerError, params
|
15
14
|
# end
|
16
15
|
#
|
17
16
|
# error_handling json: { '$.errors.code': 10..19 }, with: :my_error_handling
|
@@ -29,10 +28,11 @@ module MyApiClient
|
|
29
28
|
# @option status_code [String, Range, Integer, Regexp]
|
30
29
|
# Verifies response HTTP status code and raises error if matched
|
31
30
|
# @option json [Hash, Symbol]
|
32
|
-
#
|
33
|
-
#
|
31
|
+
# Specify the validation target value path included in the response body
|
32
|
+
# as JsonPath expression.
|
33
|
+
# If specified `:forbid_nil`, it forbid `nil` at the response body.
|
34
34
|
# @option with [Symbol]
|
35
|
-
# Calls specified method when error detected
|
35
|
+
# Calls specified method before raising exception when error detected.
|
36
36
|
# @option raise [MyApiClient::Error]
|
37
37
|
# Raises specified error when an invalid response detected.
|
38
38
|
# Should be inherited `MyApiClient::Error` class.
|
@@ -41,7 +41,7 @@ module MyApiClient
|
|
41
41
|
# If the error detected, retries the API request. Requires `raise` option.
|
42
42
|
# You can set `true` or `retry_on` options (`wait` and `attempts`).
|
43
43
|
# @yield [MyApiClient::Params::Params, MyApiClient::Request::Logger]
|
44
|
-
# Executes the block when error detected.
|
44
|
+
# Executes the block before raising exception when error detected.
|
45
45
|
# Forbid to be used with the` retry` option.
|
46
46
|
def error_handling(**options, &block)
|
47
47
|
options[:block] = block
|
@@ -23,8 +23,8 @@ module MyApiClient
|
|
23
23
|
# Raises specified error when error detected. default: MyApiClient::Error
|
24
24
|
# @option block [Proc]
|
25
25
|
# Executes the block when error detected
|
26
|
-
# @return [Proc]
|
27
|
-
# Returns
|
26
|
+
# @return [Proc, nil]
|
27
|
+
# Returns the error handler as "Proc". If no error occurs, return `nil`.
|
28
28
|
def initialize(**options)
|
29
29
|
options[:raise] ||= MyApiClient::Error
|
30
30
|
verify_and_set_arguments(**options)
|
@@ -43,14 +43,32 @@ module MyApiClient
|
|
43
43
|
|
44
44
|
def generate_error_handler
|
45
45
|
if _block
|
46
|
-
|
46
|
+
block_caller
|
47
47
|
elsif _with
|
48
|
-
|
48
|
+
method_caller
|
49
49
|
else
|
50
|
-
|
50
|
+
error_raiser
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
def block_caller
|
55
|
+
lambda { |params, logger|
|
56
|
+
_block.call(params, logger)
|
57
|
+
error_raiser.call(params, logger)
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def method_caller
|
62
|
+
lambda { |params, logger|
|
63
|
+
_instance.send(_with, params, logger)
|
64
|
+
error_raiser.call(params, logger)
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
def error_raiser
|
69
|
+
->(params, _) { raise _raise, params }
|
70
|
+
end
|
71
|
+
|
54
72
|
# Verify given options and raise error if they are incorrect.
|
55
73
|
# If not, set them to instance variables.
|
56
74
|
#
|
@@ -67,7 +85,6 @@ module MyApiClient
|
|
67
85
|
end
|
68
86
|
end
|
69
87
|
|
70
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
71
88
|
def match?(operator, target)
|
72
89
|
case operator
|
73
90
|
when nil
|
@@ -84,7 +101,6 @@ module MyApiClient
|
|
84
101
|
raise "Unexpected operator type was given: #{operator.inspect}"
|
85
102
|
end
|
86
103
|
end
|
87
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
88
104
|
|
89
105
|
def match_all?(json, response_body)
|
90
106
|
return true if json.nil?
|
data/lib/my_api_client/errors.rb
CHANGED
@@ -4,6 +4,7 @@ module MyApiClient
|
|
4
4
|
# The ancestor class for all API request error
|
5
5
|
class Error < StandardError
|
6
6
|
attr_reader :params
|
7
|
+
|
7
8
|
delegate :metadata, to: :params
|
8
9
|
alias to_bugsnag metadata
|
9
10
|
|
@@ -25,57 +26,4 @@ module MyApiClient
|
|
25
26
|
{ error: super, params: params }.inspect
|
26
27
|
end
|
27
28
|
end
|
28
|
-
|
29
|
-
NETWORK_ERRORS = [
|
30
|
-
Faraday::TimeoutError,
|
31
|
-
Faraday::ConnectionFailed,
|
32
|
-
Faraday::SSLError,
|
33
|
-
OpenSSL::SSL::SSLError,
|
34
|
-
Net::OpenTimeout,
|
35
|
-
Net::ReadTimeout,
|
36
|
-
SocketError,
|
37
|
-
].freeze
|
38
|
-
|
39
|
-
# Raises it when occurred to some network error
|
40
|
-
class NetworkError < Error
|
41
|
-
attr_reader :original_error
|
42
|
-
|
43
|
-
# Initialize the error class
|
44
|
-
#
|
45
|
-
# @param params [MyApiClient::Params::Params]
|
46
|
-
# The request and response parameters
|
47
|
-
# @param original_error [StandardError]
|
48
|
-
# Some network error
|
49
|
-
def initialize(params, original_error)
|
50
|
-
@original_error = original_error
|
51
|
-
super params, original_error.message
|
52
|
-
end
|
53
|
-
|
54
|
-
# Returns contents as string for to be readable for human
|
55
|
-
#
|
56
|
-
# @return [String] Contents as string
|
57
|
-
def inspect
|
58
|
-
{ error: original_error, params: params }.inspect
|
59
|
-
end
|
60
|
-
|
61
|
-
# Generate metadata for bugsnag.
|
62
|
-
#
|
63
|
-
# @return [Hash] Metadata for bugsnag
|
64
|
-
def metadata
|
65
|
-
super.merge(original_error: original_error.inspect)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# NOTE: The built-in error classes are following. Although they are prepared
|
70
|
-
# to save the trouble of defining, but you can create any error classes
|
71
|
-
# which inherit the ancestor error class.
|
72
|
-
|
73
|
-
# For 4xx client error
|
74
|
-
class ClientError < Error; end
|
75
|
-
|
76
|
-
# For 5xx server error
|
77
|
-
class ServerError < Error; end
|
78
|
-
|
79
|
-
# For API request limit error
|
80
|
-
class ApiLimitError < Error; end
|
81
29
|
end
|