my_api_client 0.14.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|