experian_consumer_view 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|