experian_consumer_view 1.0.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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +28 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +103 -0
- data/LICENSE.md +21 -0
- data/README.md +319 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/experian_consumer_view.gemspec +46 -0
- data/lib/experian_consumer_view.rb +3 -0
- data/lib/experian_consumer_view/api.rb +158 -0
- data/lib/experian_consumer_view/client.rb +152 -0
- data/lib/experian_consumer_view/constants.rb +5 -0
- data/lib/experian_consumer_view/errors.rb +59 -0
- data/lib/experian_consumer_view/transformers/attributes/base.rb +33 -0
- data/lib/experian_consumer_view/transformers/attributes/match.rb +22 -0
- data/lib/experian_consumer_view/transformers/attributes/postcode_mosaic_uk_7_group.rb +39 -0
- data/lib/experian_consumer_view/transformers/attributes/postcode_mosaic_uk_7_type.rb +90 -0
- data/lib/experian_consumer_view/transformers/no_op_transformer.rb +13 -0
- data/lib/experian_consumer_view/transformers/result_transformer.rb +69 -0
- data/lib/experian_consumer_view/version.rb +5 -0
- metadata +211 -0
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'experian_consumer_view'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/experian_consumer_view/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'experian_consumer_view'
|
7
|
+
spec.version = ExperianConsumerView::VERSION
|
8
|
+
spec.authors = ['Andrew Sibley']
|
9
|
+
spec.email = ['andrew.s@38degrees.org.uk']
|
10
|
+
spec.license = 'MIT'
|
11
|
+
spec.homepage = 'https://github.com/38degrees/experian_consumer_view'
|
12
|
+
spec.summary = "Ruby wrapper for Experian's ConsumerView API."
|
13
|
+
spec.description = "
|
14
|
+
Experian's ConsumerView API is a commercially licensed API which allows you
|
15
|
+
to obtain various demographic data on UK consumers at the postcode, household,
|
16
|
+
and individual level. This gem provides a simple Ruby wrapper to use the API.
|
17
|
+
"
|
18
|
+
|
19
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
|
20
|
+
|
21
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
22
|
+
# spec.metadata["homepage_uri"] = spec.homepage
|
23
|
+
# spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
24
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
25
|
+
|
26
|
+
# Specify which files should be added to the gem when it is released.
|
27
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
28
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
29
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
30
|
+
end
|
31
|
+
spec.bindir = 'exe'
|
32
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
33
|
+
spec.require_paths = ['lib']
|
34
|
+
|
35
|
+
spec.add_dependency 'activesupport', '>= 5.2'
|
36
|
+
spec.add_dependency 'faraday', '~> 1.0'
|
37
|
+
|
38
|
+
spec.add_development_dependency 'bundler', '~> 2.1'
|
39
|
+
spec.add_development_dependency 'codecov', '>= 0.2'
|
40
|
+
spec.add_development_dependency 'pry', '>= 0.12'
|
41
|
+
spec.add_development_dependency 'rake', '>= 12.0'
|
42
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
43
|
+
spec.add_development_dependency 'rubocop', '~> 0.91.0'
|
44
|
+
spec.add_development_dependency 'webmock', '~> 3.9'
|
45
|
+
spec.add_development_dependency 'yard', '~> 0.9.25'
|
46
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'errors'
|
4
|
+
|
5
|
+
require 'faraday'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
module ExperianConsumerView
|
9
|
+
# Low-level class for accessing the Experian ConsumerView API. It is not recommended to use this class directly.
|
10
|
+
# The +ExperianConsumerView::Client+ class is designed to be directly used by applications.
|
11
|
+
#
|
12
|
+
# This class provides low-level access to make specific HTTP calls to the ConsumerView API, such as logging in to get
|
13
|
+
# an authorisation token, and performing lookups of an individual / household / postcode.
|
14
|
+
class Api
|
15
|
+
include ExperianConsumerView::Errors
|
16
|
+
|
17
|
+
PRODUCTION_URL = 'https://neartime.experian.co.uk'
|
18
|
+
STAGING_URL = 'https://stg.neartime.experian.co.uk'
|
19
|
+
|
20
|
+
LOGIN_PATH = '/overture/login'
|
21
|
+
SINGLE_LOOKUP_PATH = '/overture/lookup'
|
22
|
+
BATCH_LOOKUP_PATH = '/overture/batch'
|
23
|
+
|
24
|
+
# @param url [String] optional base URL for the API wrapper to connect to. Defaults to the Experian ConsumerView
|
25
|
+
# production server.
|
26
|
+
def initialize(url: nil)
|
27
|
+
@httpclient = Faraday.new(
|
28
|
+
url: url || PRODUCTION_URL,
|
29
|
+
headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' }
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Logs in to the Experian ConsumerView API, and gets an authorization token.
|
34
|
+
#
|
35
|
+
# @param user_id [String] the username / email used to authorize use of the ConsumerView API
|
36
|
+
# @param password [String] the password used to authorize use of the ConsumerView API
|
37
|
+
def get_auth_token(user_id:, password:)
|
38
|
+
query_params = { 'userid' => user_id, 'password' => password }
|
39
|
+
|
40
|
+
result = @httpclient.post(LOGIN_PATH, query_params.to_json)
|
41
|
+
check_http_result_status(result)
|
42
|
+
|
43
|
+
JSON.parse(result.body)['token']
|
44
|
+
end
|
45
|
+
|
46
|
+
# Looks up demographic data for a single individual / household / postcode.
|
47
|
+
#
|
48
|
+
# Note that the demographic / propensity keys returned will only be those which the given client & asset have access
|
49
|
+
# to. Refer to the Experian ConsumerView API Documentation for exact details of the keys & possible values.
|
50
|
+
#
|
51
|
+
# @param user_id [String] the username / email used to authorize use of the ConsumerView API
|
52
|
+
# @param token [String] the time-limited authorization token provided when logging into the API
|
53
|
+
# @param client_id [String] your 5-digit Experian client ID
|
54
|
+
# @param asset_id [String] your 6-character Experian asset ID
|
55
|
+
# @param search_keys [Hash] hash containing the keys required to look up an individual / household / postcode.
|
56
|
+
# Refer to the Experian ConsumerView API Documentation for exact details on the required keys.
|
57
|
+
#
|
58
|
+
# @return [Hash] a hash containing a key/value pair for each demographic / propensity for the individual / household
|
59
|
+
# / postcode which was successfully looked up. Returns an empty hash if the lookup does not find any matches.
|
60
|
+
def single_lookup(user_id:, token:, client_id:, asset_id:, search_keys:)
|
61
|
+
# TODO: Delete this if looking up a single item via the batch method isn't any slower - no point supporting both!
|
62
|
+
|
63
|
+
query_params = {
|
64
|
+
'ssoId' => user_id,
|
65
|
+
'token' => token,
|
66
|
+
'clientId' => client_id,
|
67
|
+
'assetId' => asset_id
|
68
|
+
}
|
69
|
+
query_params.merge!(search_keys)
|
70
|
+
|
71
|
+
result = @httpclient.post(SINGLE_LOOKUP_PATH, query_params.to_json)
|
72
|
+
check_http_result_status(result)
|
73
|
+
|
74
|
+
JSON.parse(result.body)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Looks up demographic data for a batch of individuals / households / postcodes.
|
78
|
+
#
|
79
|
+
# Note that the demographic / propensity keys returned will only be those which the given client & asset have access
|
80
|
+
# to. Refer to the Experian ConsumerView API Documentation for exact details of the keys & possible values.
|
81
|
+
#
|
82
|
+
# @param user_id [String] the username / email used to authorize use of the ConsumerView API
|
83
|
+
# @param token [String] the time-limited authorization token provided when logging into the API
|
84
|
+
# @param client_id [String] your 5-digit Experian client ID
|
85
|
+
# @param asset_id [String] your 6-character Experian asset ID
|
86
|
+
# @param search_keys [Array<Hash>] an array of hashes, each hash containing the keys required to look up an
|
87
|
+
# individual / household / postcode. Refer to the Experian ConsumerView API Documentation for exact details on the
|
88
|
+
# required keys.
|
89
|
+
#
|
90
|
+
# @return [Array<Hash>] an array of hashes, each hash containing a key/value pair for each demographic / propensity
|
91
|
+
# for the individual / household / postcode which was successfully looked up. Returns an empty hash for any items
|
92
|
+
# in the batch where no matches were found. The order of the results array is the same as the order of the
|
93
|
+
# supplied search array - ie. element 0 of the results array contains the hash of demographic data for the
|
94
|
+
# individual / household / postcode supplied in position 0 of the batch of search keys.
|
95
|
+
def batch_lookup(user_id:, token:, client_id:, asset_id:, batched_search_keys:)
|
96
|
+
raise ApiBatchTooBigError if batched_search_keys.length > ExperianConsumerView::MAX_LOOKUP_BATCH_SIZE
|
97
|
+
|
98
|
+
query_params = {
|
99
|
+
'ssoId' => user_id,
|
100
|
+
'token' => token,
|
101
|
+
'clientId' => client_id,
|
102
|
+
'assetId' => asset_id,
|
103
|
+
'batch' => batched_search_keys
|
104
|
+
}
|
105
|
+
|
106
|
+
result = @httpclient.post(BATCH_LOOKUP_PATH, query_params.to_json)
|
107
|
+
check_http_result_status(result)
|
108
|
+
|
109
|
+
JSON.parse(result.body)
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
# Helper to check the result, and throw an appropriate error if something went wrong
|
115
|
+
def check_http_result_status(result)
|
116
|
+
return if result.status == 200
|
117
|
+
|
118
|
+
# An error occurred - attempt to extract the response string from the body if we can
|
119
|
+
response = get_response(result)
|
120
|
+
|
121
|
+
case result.status
|
122
|
+
when 401
|
123
|
+
raise ApiBadCredentialsError.new(result.status, response)
|
124
|
+
when 404
|
125
|
+
raise ApiEndpointNotFoundError.new(result.status, response)
|
126
|
+
when 417
|
127
|
+
raise ApiIncorrectJsonError.new(result.status, response)
|
128
|
+
when 500
|
129
|
+
raise ApiServerError.new(result.status, response)
|
130
|
+
when 503
|
131
|
+
raise ApiServerRefreshingError(result.status, response) if response == 'Internal refresh in progress'
|
132
|
+
|
133
|
+
raise ApiServerError.new(result.status, response)
|
134
|
+
when 515
|
135
|
+
raise ApiHttpVersionNotSupportedError.new(result.status, response)
|
136
|
+
else
|
137
|
+
raise ApiUnhandledHttpError.new(result.status, response)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def get_response(result)
|
142
|
+
# TODO: Temp debugging for convenience
|
143
|
+
# puts result.body.class.to_s
|
144
|
+
# puts result.body.to_s
|
145
|
+
|
146
|
+
# TODO: Is this complex handling necessary? Check if all types of error are consistent in the body they return...
|
147
|
+
if result.body&.is_a?(Hash)
|
148
|
+
result.body['response']
|
149
|
+
elsif result.body&.is_a?(String)
|
150
|
+
JSON.parse(result.body)['response']
|
151
|
+
else
|
152
|
+
''
|
153
|
+
end
|
154
|
+
rescue JSON::ParserError
|
155
|
+
''
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'errors'
|
4
|
+
require_relative 'transformers/result_transformer'
|
5
|
+
|
6
|
+
require 'active_support'
|
7
|
+
require 'active_support/cache'
|
8
|
+
|
9
|
+
module ExperianConsumerView
|
10
|
+
# Top-level wrapper for accessing the ExperianConsumerView API. Once an instance is created with the appropriate
|
11
|
+
# credentials, the +lookup+ method provides the ability to lookup individuals, households, or postcodes in the
|
12
|
+
# ConsumerView API and return all the data your account has access to.
|
13
|
+
#
|
14
|
+
# This class automatically handles logging in to the ConsumerView API, obtaining an authorisation token (which is
|
15
|
+
# valid for approximately 30 minutes), and then looking up the data. The authorisation token is cached so that it's
|
16
|
+
# not necessary to login again for every single lookup request.
|
17
|
+
#
|
18
|
+
# Note that by default the authorisation is cached in-memory using +ActiveSupport::Cache::MemoryStore+. This is
|
19
|
+
# suitable for single-server applications, but is unlikely to be suitable for distributed applications, or those
|
20
|
+
# hosted on cloud infrastructure. A distributed cache, such as +ActiveSupport::Cache::RedisCacheStore+ or
|
21
|
+
# +ActiveSupport::Cache::MemCacheStore+ is recommended for distributed or cloud-hosted applications.
|
22
|
+
#
|
23
|
+
# If an in-memory data-store were used in distributed or cloud-hosted applications, then the multiple servers will be
|
24
|
+
# unaware of each others tokens, and therefore each server would login to the ConsumerView API independently, even if
|
25
|
+
# another server already had a valid token. Logging in to the ConsumerView API multiple times with the same
|
26
|
+
# credentials will revoke prior tokens, meaning other servers will find their cached tokens are invalid the next time
|
27
|
+
# they try a lookup. This will likely lead to a situation where many lookup attempts fail the first time due to the
|
28
|
+
# server in question not having the most up-to-date token.
|
29
|
+
class Client
|
30
|
+
include ExperianConsumerView::Errors
|
31
|
+
|
32
|
+
CACHE_KEY = 'ExperianConsumerView::Client::CachedToken'
|
33
|
+
|
34
|
+
attr_writer :result_transformer
|
35
|
+
|
36
|
+
# @param user_id [String] the username / email used to authorize use of the ConsumerView API
|
37
|
+
# @param password [String] the password used to authorize use of the ConsumerView API
|
38
|
+
# @param client_id [String] your 5-digit Experian client ID
|
39
|
+
# @param asset_id [String] your 6-character Experian asset ID
|
40
|
+
# @param options [Hash] a hash of advanced options for configuring the client
|
41
|
+
#
|
42
|
+
# @option options [ActiveSupport::Cache] :token_cache optional cache to store login tokens. If no cache is provided,
|
43
|
+
# a default in-memory cache is used, however such a cache is not suitable for distributed or cloud environments,
|
44
|
+
# and will likely result in frequently invalidating the Experian ConsumerView authorization token.
|
45
|
+
# @option options [#transform] :result_transformer optional object whose +transform+ method accepts a hash
|
46
|
+
# containing the results returned by the ConsumerView API for a single individual, household or postcode, and
|
47
|
+
# transforms this hash into the desired output. By default, an instance of +ResultTransformer+ is used, which will
|
48
|
+
# transform some common attributes returned by the ConsumerView API into hashes with richer details than returned
|
49
|
+
# by the raw API.
|
50
|
+
# @option options [String] :api_base_url optional base URL to make ConsumerView API calls against. By default, uses
|
51
|
+
# the Experian production ConsumerView server.
|
52
|
+
def initialize(user_id:, password:, client_id:, asset_id:, options: {})
|
53
|
+
@user_id = user_id
|
54
|
+
@password = password
|
55
|
+
@client_id = client_id
|
56
|
+
@asset_id = asset_id
|
57
|
+
|
58
|
+
@token_cache = options[:token_cache] || default_token_cache
|
59
|
+
@result_transformer = options[:result_transformer] || default_result_transformer
|
60
|
+
@api = ExperianConsumerView::Api.new(url: options[:api_base_url])
|
61
|
+
end
|
62
|
+
|
63
|
+
# Looks up 1 or more search items in the ConsumerView API.
|
64
|
+
#
|
65
|
+
# Note that the demographic / propensity keys returned will only be those which the client & asset have access to.
|
66
|
+
# Refer to the Experian ConsumerView API Documentation for exact details of the keys & possible values.
|
67
|
+
#
|
68
|
+
# @param search_items [Hash] a hash of identifiers to search keys for an individual / household / postcode as
|
69
|
+
# required by the ConsumerView API. Eg.
|
70
|
+
# <tt>{ "PersonA" => { "email" => "person.a@example.com" }, "Postcode1" => { "postcode" => "SW1A 1AA" } }</tt>.
|
71
|
+
# Note that the top-level key is not passed to the ConsumerView API, it is just used for convenience when
|
72
|
+
# returning results.
|
73
|
+
# @param auto_retries [Integer] optional number of times the lookup should be retried if a transient / potentially
|
74
|
+
# recoverable error occurs. Defaults to 1.
|
75
|
+
#
|
76
|
+
# @returns [Hash] a hash of identifiers to the results returned by the ConsumerView API. Eg.
|
77
|
+
# <tt>
|
78
|
+
# {
|
79
|
+
# "PersonA" => { "pc_mosaic_uk_7_group":"G", "Match":"P" } ,
|
80
|
+
# "Postcode1" => { "pc_mosaic_uk_7_group":"G", "Match":"PC" }
|
81
|
+
# }
|
82
|
+
# </tt>
|
83
|
+
def lookup(search_items:, auto_retries: 1)
|
84
|
+
ordered_identifiers = search_items.keys
|
85
|
+
ordered_terms = search_items.values
|
86
|
+
|
87
|
+
token = auth_token
|
88
|
+
attempts = 0
|
89
|
+
begin
|
90
|
+
ordered_results = @api.batch_lookup(
|
91
|
+
user_id: @user_id,
|
92
|
+
token: token,
|
93
|
+
client_id: @client_id,
|
94
|
+
asset_id: @asset_id,
|
95
|
+
batched_search_keys: ordered_terms
|
96
|
+
)
|
97
|
+
rescue ApiBadCredentialsError, ApiServerRefreshingError => e
|
98
|
+
# Bad Credentials can sometimes be caused by race conditions - eg. one thread / server updating the cached
|
99
|
+
# token while another is querying with the old token. Retrying once should avoid the client throwing
|
100
|
+
# unnecessary errors to the calling code.
|
101
|
+
# Experian docs also recommend retrying when a server refresh is in progress, and if that fails, retrying again
|
102
|
+
# in approximately 10 minutes.
|
103
|
+
raise e unless attempts < auto_retries
|
104
|
+
|
105
|
+
token = auth_token(force_lookup: true)
|
106
|
+
attempts += 1
|
107
|
+
retry
|
108
|
+
end
|
109
|
+
|
110
|
+
results_hash(identifiers: ordered_identifiers, results: ordered_results)
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def auth_token(force_lookup: false)
|
116
|
+
# ConsumerView auth tokens last for 30 minutes before expiring & becoming invalid.
|
117
|
+
# After 29 minutes, the cache entry will expire, and the first process to find the expired entry will refresh it,
|
118
|
+
# while allowing other processes to use the existing value for another 10s. This should alleviate race conditions,
|
119
|
+
# but will not eliminate them entirely. Note that in a distributed / cloud / multi-server environment, a shared
|
120
|
+
# cache MUST be used. An in-memory store would mean multiple instances logging to the ConsumerView API, and each
|
121
|
+
# login will change the active token, which other servers will not see, leading to frequent authorisation
|
122
|
+
# failures.
|
123
|
+
@token_cache.fetch(
|
124
|
+
CACHE_KEY, expires_in: 29.minutes, race_condition_ttl: 10.seconds, force: force_lookup
|
125
|
+
) do
|
126
|
+
@api.get_auth_token(user_id: @user_id, password: @password)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def results_hash(identifiers:, results:)
|
131
|
+
raise ApiResultSizeMismatchError unless results.size == identifiers.size
|
132
|
+
|
133
|
+
# Construct a hash of { identifier => result_hash }
|
134
|
+
# Hash[identifiers.zip(results)]
|
135
|
+
|
136
|
+
results_hash = {}
|
137
|
+
results.each_with_index do |single_result, i|
|
138
|
+
results_hash[identifiers[i]] = @result_transformer.transform(single_result)
|
139
|
+
end
|
140
|
+
|
141
|
+
results_hash
|
142
|
+
end
|
143
|
+
|
144
|
+
def default_token_cache
|
145
|
+
ActiveSupport::Cache::MemoryStore.new
|
146
|
+
end
|
147
|
+
|
148
|
+
def default_result_transformer
|
149
|
+
ExperianConsumerView::Transformers::ResultTransformer.default
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ExperianConsumerView
|
4
|
+
module Errors
|
5
|
+
# Base helper class for errors caused due to unexpected HTTP responses
|
6
|
+
class ApiHttpError < StandardError
|
7
|
+
attr_reader :code, :response
|
8
|
+
|
9
|
+
def initialize(code, response)
|
10
|
+
super()
|
11
|
+
@code = code
|
12
|
+
@response = response
|
13
|
+
end
|
14
|
+
|
15
|
+
def message
|
16
|
+
"HTTP code [#{@code}], response text [#{@response}]"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Thrown for HTTP 401 codes. This means there is a problem with some of the supplied credentials. Race conditions
|
21
|
+
# may lead to out-of-date or invalid API tokens occasionally. These errors may be auto-retried.
|
22
|
+
class ApiBadCredentialsError < ApiHttpError; end
|
23
|
+
|
24
|
+
# Thrown for HTTP 404 codes. These imply the API endpoints may have changed, likely requiring a code change to
|
25
|
+
# this code library.
|
26
|
+
class ApiEndpointNotFoundError < ApiHttpError; end
|
27
|
+
|
28
|
+
# Thrown for HTTP 417 codes. These imply the API format may have changed, likely requiring a code change to this
|
29
|
+
# code library.
|
30
|
+
class ApiIncorrectJsonError < ApiHttpError; end
|
31
|
+
|
32
|
+
# Thrown for HTTP 500 codes, and HTTP 503 codes where the text response is "Server error". This means a serious
|
33
|
+
# server error has occurred. This can only be resolved on the server side by Experian - inform them if it persists.
|
34
|
+
class ApiServerError < ApiHttpError; end
|
35
|
+
|
36
|
+
# Thrown for HTTP 503 codes where the text response is "Internal refresh in progress". This means the server is
|
37
|
+
# temporarily down while data is being refreshed, but the request should complete successfully once the refresh
|
38
|
+
# operation is complete. These errors may be auto-retried.
|
39
|
+
class ApiServerRefreshingError < ApiHttpError; end
|
40
|
+
|
41
|
+
# Thrown for HTTP 505 codes. These imply an error which likely requires a code change to this code library.
|
42
|
+
class ApiHttpVersionNotSupportedError < ApiHttpError; end
|
43
|
+
|
44
|
+
# Thrown for unhandled HTTP codes.
|
45
|
+
class ApiUnhandledHttpError < ApiHttpError; end
|
46
|
+
|
47
|
+
# Thrown when the API is passed a batch which is too big to be given to the API
|
48
|
+
class ApiBatchTooBigError < StandardError; end
|
49
|
+
|
50
|
+
# Thrown when the API returns data successfully, but the size of the data returned does not match the size of the
|
51
|
+
# query data provided, meaning there is no way to know for sure which result relates to which query string. Such
|
52
|
+
# an error either implies a serious issue with the Experian API, or with this code library (or a change to the API
|
53
|
+
# contract).
|
54
|
+
class ApiResultSizeMismatchError < StandardError; end
|
55
|
+
|
56
|
+
# Thrown when the API returns a value for an attribute which is unrecognised and therefore can't be transformed
|
57
|
+
class AttributeValueUnrecognisedError < StandardError; end
|
58
|
+
end
|
59
|
+
end
|