rosette_api 1.14.4 → 1.37.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/LICENSE +1 -1
- data/README.md +23 -16
- data/examples/README.md +2 -2
- data/examples/address_similarity.rb +7 -6
- data/examples/categories.rb +9 -8
- data/examples/entities.rb +8 -8
- data/examples/events.rb +23 -0
- data/examples/info.rb +7 -6
- data/examples/language.rb +7 -6
- data/examples/language_multilingual.rb +7 -6
- data/examples/morphology_complete.rb +7 -6
- data/examples/morphology_compound-components.rb +7 -6
- data/examples/morphology_han-readings.rb +7 -6
- data/examples/morphology_lemmas.rb +7 -6
- data/examples/morphology_parts-of-speech.rb +7 -6
- data/examples/multipart_language_file.rb +29 -0
- data/examples/name_deduplication.rb +7 -6
- data/examples/name_similarity.rb +9 -7
- data/examples/name_translation.rb +7 -6
- data/examples/ping.rb +7 -6
- data/examples/record_similarity.rb +114 -0
- data/examples/relationships.rb +7 -6
- data/examples/semantic_vectors.rb +7 -6
- data/examples/sentences.rb +7 -6
- data/examples/sentiment.rb +8 -7
- data/examples/similar_terms.rb +7 -6
- data/examples/syntax_dependencies.rb +7 -6
- data/examples/tokens.rb +7 -6
- data/examples/topics.rb +7 -6
- data/examples/transliteration.rb +7 -6
- data/lib/address_parameter.rb +3 -4
- data/lib/address_similarity_parameters.rb +13 -6
- data/lib/bad_request_error.rb +3 -3
- data/lib/bad_request_format_error.rb +3 -3
- data/lib/document_parameters.rb +10 -12
- data/lib/name_deduplication_parameters.rb +5 -8
- data/lib/name_parameter.rb +22 -5
- data/lib/name_similarity_parameters.rb +51 -21
- data/lib/name_translation_parameters.rb +17 -10
- data/lib/record_similarity_parameters.rb +68 -0
- data/lib/request_builder.rb +94 -54
- data/lib/rosette_api.rb +90 -50
- data/lib/rosette_api_error.rb +5 -4
- metadata +28 -33
|
@@ -4,26 +4,28 @@ require_relative 'bad_request_error'
|
|
|
4
4
|
require_relative 'name_parameter'
|
|
5
5
|
|
|
6
6
|
# This class encapsulates parameters that are needed for name-similarity in
|
|
7
|
-
#
|
|
7
|
+
# Analytics API.
|
|
8
8
|
class NameSimilarityParameters
|
|
9
9
|
# genre to categorize the input data
|
|
10
10
|
attr_accessor :genre
|
|
11
|
+
# Deprecated: Retained for backward compatibility. Use 'parameters' instead.
|
|
11
12
|
# Rosette API options (optional, should be a hash)
|
|
12
13
|
attr_accessor :rosette_options
|
|
14
|
+
# Parameters map sent to the API (optional, should be a hash)
|
|
15
|
+
attr_accessor :parameters
|
|
13
16
|
# Name to be compared to name2
|
|
14
17
|
attr_accessor :name1
|
|
15
18
|
# Name to be compared to name1
|
|
16
19
|
attr_accessor :name2
|
|
17
20
|
|
|
18
|
-
def initialize(name1, name2,
|
|
19
|
-
options = {
|
|
20
|
-
genre: nil,
|
|
21
|
-
rosette_options: nil
|
|
22
|
-
}.update options
|
|
23
|
-
@genre = options[:genre]
|
|
21
|
+
def initialize(name1, name2, match_parameters = nil) # :notnew:
|
|
24
22
|
@name1 = name1
|
|
25
23
|
@name2 = name2
|
|
26
|
-
@
|
|
24
|
+
@genre = nil
|
|
25
|
+
@parameters = nil
|
|
26
|
+
@rosette_options = nil
|
|
27
|
+
|
|
28
|
+
handle_match_parameters(match_parameters) if match_parameters
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
# Validates the parameters by checking if name1 and name2 are instances of
|
|
@@ -35,10 +37,11 @@ class NameSimilarityParameters
|
|
|
35
37
|
n2_msg = 'name2 option can only be an instance of a String or NameParameter'
|
|
36
38
|
raise BadRequestError.new(n2_msg) if [String, NameParameter].none? { |clazz| @name2.is_a? clazz }
|
|
37
39
|
|
|
38
|
-
opt_msg = '
|
|
39
|
-
if @
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
opt_msg = 'parameters can only be an instance of a Hash'
|
|
41
|
+
raise BadRequestError.new(opt_msg) if @parameters && !(@parameters.is_a? Hash)
|
|
42
|
+
|
|
43
|
+
rosette_opt_msg = 'rosette_options can only be an instance of a Hash'
|
|
44
|
+
raise BadRequestError.new(rosette_opt_msg) if @rosette_options && !(@rosette_options.is_a? Hash)
|
|
42
45
|
end
|
|
43
46
|
|
|
44
47
|
# Converts this class to Hash with its keys in lower CamelCase.
|
|
@@ -47,20 +50,47 @@ class NameSimilarityParameters
|
|
|
47
50
|
def load_params
|
|
48
51
|
validate_params
|
|
49
52
|
to_hash
|
|
50
|
-
.
|
|
51
|
-
.
|
|
52
|
-
.to_h
|
|
53
|
+
.compact
|
|
54
|
+
.transform_keys { |key| key.to_s.split('_').map(&:capitalize).join.sub!(/\D/, &:downcase) }
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
# Converts this class to Hash.
|
|
56
58
|
#
|
|
57
59
|
# Returns the new Hash.
|
|
58
60
|
def to_hash
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
if @parameters
|
|
62
|
+
{
|
|
63
|
+
name1: @name1.is_a?(NameParameter) ? @name1.load_param : @name1,
|
|
64
|
+
name2: @name2.is_a?(NameParameter) ? @name2.load_param : @name2,
|
|
65
|
+
parameters: @parameters
|
|
66
|
+
}
|
|
67
|
+
else
|
|
68
|
+
{
|
|
69
|
+
genre: @genre,
|
|
70
|
+
name1: @name1.is_a?(NameParameter) ? @name1.load_param : @name1,
|
|
71
|
+
name2: @name2.is_a?(NameParameter) ? @name2.load_param : @name2,
|
|
72
|
+
options: @rosette_options
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
# Processes the 3rd argument to determine if it is using the legacy 'options' signature
|
|
80
|
+
# or the new 'match_parameters' signature, and assigns instance variables accordingly.
|
|
81
|
+
def handle_match_parameters(match_parameters)
|
|
82
|
+
if legacy_options?(match_parameters)
|
|
83
|
+
warn 'DEPRECATION WARNING: Passing `options` dynamically via NameSimilarityParameters.new is deprecated. Please pass `parameters` instead.'
|
|
84
|
+
@genre = match_parameters[:genre] || match_parameters['genre']
|
|
85
|
+
@rosette_options = match_parameters[:rosette_options] || match_parameters['rosette_options']
|
|
86
|
+
else
|
|
87
|
+
@parameters = match_parameters
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def legacy_options?(params)
|
|
92
|
+
return false unless params.is_a?(Hash)
|
|
93
|
+
|
|
94
|
+
params.key?(:genre) || params.key?('genre') || params.key?(:rosette_options) || params.key?('rosette_options')
|
|
65
95
|
end
|
|
66
96
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require_relative 'rosette_api_error'
|
|
4
4
|
|
|
5
5
|
# This class encapsulates parameters that are needed for name-translation in
|
|
6
|
-
#
|
|
6
|
+
# Analytics API.
|
|
7
7
|
class NameTranslationParameters
|
|
8
8
|
# Name's entity type (PERSON, LOCATION, ORGANIZATION) (optional)
|
|
9
9
|
attr_accessor :entity_type
|
|
@@ -11,7 +11,7 @@ class NameTranslationParameters
|
|
|
11
11
|
attr_accessor :genre
|
|
12
12
|
# Name to translate
|
|
13
13
|
attr_accessor :name
|
|
14
|
-
#
|
|
14
|
+
# API options (optional, should be a hash)
|
|
15
15
|
attr_accessor :rosette_options
|
|
16
16
|
# ISO 693-3 code of the name's native language the name originates in
|
|
17
17
|
# (optional)
|
|
@@ -26,11 +26,14 @@ class NameTranslationParameters
|
|
|
26
26
|
attr_accessor :target_scheme
|
|
27
27
|
# ISO 15924 code of name's script (optional)
|
|
28
28
|
attr_accessor :target_script
|
|
29
|
+
# Maximum number of results to return (optional)
|
|
30
|
+
attr_accessor :maximum_results
|
|
29
31
|
|
|
30
|
-
def initialize(name, target_language, options = {})
|
|
32
|
+
def initialize(name, target_language, options = {}) # :notnew:
|
|
31
33
|
options = {
|
|
32
34
|
entity_type: nil,
|
|
33
35
|
genre: nil,
|
|
36
|
+
maximum_results: nil,
|
|
34
37
|
rosette_options: nil,
|
|
35
38
|
source_language_of_origin: nil,
|
|
36
39
|
source_language_of_use: nil,
|
|
@@ -41,6 +44,7 @@ class NameTranslationParameters
|
|
|
41
44
|
@name = name
|
|
42
45
|
@entity_type = options[:entity_type]
|
|
43
46
|
@genre = options[:genre]
|
|
47
|
+
@maximum_results = options[:maximum_results]
|
|
44
48
|
@rosette_options = options[:rosette_options]
|
|
45
49
|
@source_language_of_origin = options[:source_language_of_origin]
|
|
46
50
|
@source_language_of_use = options[:source_language_of_use]
|
|
@@ -54,9 +58,13 @@ class NameTranslationParameters
|
|
|
54
58
|
# of a Hash.
|
|
55
59
|
def validate_params
|
|
56
60
|
msg = 'rosette_options can only be an instance of a Hash'
|
|
57
|
-
if @rosette_options
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
raise BadRequestError.new(msg) if @rosette_options && !(@rosette_options.is_a? Hash)
|
|
62
|
+
|
|
63
|
+
max_msg = 'maximum_results can only be an instance of an Integer'
|
|
64
|
+
raise BadRequestError.new(max_msg) if @maximum_results && !(@maximum_results.is_a? Integer)
|
|
65
|
+
|
|
66
|
+
max_range_msg = 'maximum_results must be greater than or equal to 0'
|
|
67
|
+
raise BadRequestError.new(max_range_msg) if @maximum_results&.negative?
|
|
60
68
|
end
|
|
61
69
|
|
|
62
70
|
# Converts this class to Hash with its keys in lower CamelCase.
|
|
@@ -66,8 +74,7 @@ class NameTranslationParameters
|
|
|
66
74
|
validate_params
|
|
67
75
|
to_hash
|
|
68
76
|
.select { |_key, value| value }
|
|
69
|
-
.
|
|
70
|
-
.to_h
|
|
77
|
+
.transform_keys { |key| key.to_s.split('_').map(&:capitalize).join.sub!(/\D/, &:downcase) }
|
|
71
78
|
end
|
|
72
79
|
|
|
73
80
|
# Converts this class to Hash.
|
|
@@ -76,7 +83,6 @@ class NameTranslationParameters
|
|
|
76
83
|
def to_hash
|
|
77
84
|
{
|
|
78
85
|
entity_type: @entity_type,
|
|
79
|
-
genre: @genre,
|
|
80
86
|
name: @name,
|
|
81
87
|
options: @rosette_options,
|
|
82
88
|
source_language_of_origin: @source_language_of_origin,
|
|
@@ -84,7 +90,8 @@ class NameTranslationParameters
|
|
|
84
90
|
source_script: @source_script,
|
|
85
91
|
target_language: @target_language,
|
|
86
92
|
target_scheme: @target_scheme,
|
|
87
|
-
target_script: @target_script
|
|
93
|
+
target_script: @target_script,
|
|
94
|
+
maximum_results: @maximum_results
|
|
88
95
|
}
|
|
89
96
|
end
|
|
90
97
|
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'bad_request_error'
|
|
4
|
+
|
|
5
|
+
# This class encapsulates parameters that are needed for record-similarity in
|
|
6
|
+
# Analytics API.
|
|
7
|
+
class RecordSimilarityParameters
|
|
8
|
+
# Records to be compared (required)
|
|
9
|
+
attr_accessor :records
|
|
10
|
+
|
|
11
|
+
# Field names/definitions used for similarity scoring (required)
|
|
12
|
+
attr_accessor :fields
|
|
13
|
+
|
|
14
|
+
# Optional properties map sent to the API (optional, should be a hash)
|
|
15
|
+
attr_accessor :properties
|
|
16
|
+
|
|
17
|
+
def initialize(fields, records, properties = nil) # :notnew:
|
|
18
|
+
@fields = fields
|
|
19
|
+
@records = records
|
|
20
|
+
@properties = properties
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Validates the parameters by checking if required fields are present and
|
|
24
|
+
# optional properties is a Hash if provided.
|
|
25
|
+
def validate_params
|
|
26
|
+
f_msg = 'fields option is required'
|
|
27
|
+
raise BadRequestError.new(f_msg) if @fields.nil?
|
|
28
|
+
|
|
29
|
+
f_type_msg = 'fields can only be an instance of a Hash'
|
|
30
|
+
raise BadRequestError.new(f_type_msg) unless @fields.is_a? Hash
|
|
31
|
+
|
|
32
|
+
f_empty_msg = 'fields must not be empty'
|
|
33
|
+
raise BadRequestError.new(f_empty_msg) if @fields.empty?
|
|
34
|
+
|
|
35
|
+
r_msg = 'records option is required'
|
|
36
|
+
raise BadRequestError.new(r_msg) if @records.nil?
|
|
37
|
+
|
|
38
|
+
r_type_msg = 'records can only be an instance of a Hash'
|
|
39
|
+
raise BadRequestError.new(r_type_msg) unless @records.is_a? Hash
|
|
40
|
+
|
|
41
|
+
r_empty_msg = 'records must not be empty'
|
|
42
|
+
raise BadRequestError.new(r_empty_msg) if @records.empty?
|
|
43
|
+
|
|
44
|
+
p_msg = 'properties can only be an instance of a Hash'
|
|
45
|
+
raise BadRequestError.new(p_msg) if @properties && !(@properties.is_a? Hash)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Converts this class to Hash with its keys in lower CamelCase.
|
|
49
|
+
#
|
|
50
|
+
# Returns the new Hash.
|
|
51
|
+
def load_params
|
|
52
|
+
validate_params
|
|
53
|
+
to_hash
|
|
54
|
+
.compact
|
|
55
|
+
.transform_keys { |key| key.to_s.split('_').map(&:capitalize).join.sub!(/\D/, &:downcase) }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Converts this class to Hash.
|
|
59
|
+
#
|
|
60
|
+
# Returns the new Hash.
|
|
61
|
+
def to_hash
|
|
62
|
+
{
|
|
63
|
+
fields: @fields,
|
|
64
|
+
records: @records,
|
|
65
|
+
properties: @properties
|
|
66
|
+
}
|
|
67
|
+
end
|
|
68
|
+
end
|
data/lib/request_builder.rb
CHANGED
|
@@ -6,17 +6,45 @@ require 'json'
|
|
|
6
6
|
require 'securerandom'
|
|
7
7
|
require_relative 'rosette_api_error'
|
|
8
8
|
|
|
9
|
-
# This class handles all
|
|
9
|
+
# This class handles all Analytics API requests.
|
|
10
10
|
class RequestBuilder
|
|
11
|
-
|
|
11
|
+
CONNECTION_ERROR_CODE = 'connectionError'
|
|
12
|
+
CONNECTION_ERROR_MESSAGE = 'Failed to establish connection with Analytics server.'
|
|
13
|
+
|
|
14
|
+
INVALID_HEADER_CODE = 'invalidHeader'
|
|
15
|
+
INVALID_HEADER_MESSAGE = 'Custom header must begin with "X-RosetteAPI-" or "X-BabelStreetAPI-"'
|
|
16
|
+
|
|
17
|
+
READ_MULTIPART_ERROR_CODE = 'readMultipartError'
|
|
18
|
+
|
|
19
|
+
HEADER_API_KEY = 'X-BabelStreetAPI-Key'
|
|
20
|
+
HEADER_CONTENT_TYPE = 'Content-Type'
|
|
21
|
+
HEADER_ACCEPT = 'Accept'
|
|
22
|
+
HEADER_USER_AGENT = 'User-Agent'
|
|
23
|
+
HEADER_BINDING_LEGACY = 'X-RosetteAPI-Binding'
|
|
24
|
+
HEADER_BINDING = 'X-BabelStreetAPI-Binding'
|
|
25
|
+
HEADER_BINDING_VERSION_LEGACY = 'X-RosetteAPI-Binding-Version'
|
|
26
|
+
HEADER_BINDING_VERSION = 'X-BabelStreetAPI-Binding-Version'
|
|
27
|
+
|
|
28
|
+
BINDING_NAME = 'ruby'
|
|
29
|
+
|
|
30
|
+
CONTENT_TYPE_JSON = 'application/json'
|
|
31
|
+
CONTENT_TYPE_TEXT_PLAIN = 'text/plain'
|
|
32
|
+
ACCEPT_JSON = 'application/json'
|
|
33
|
+
|
|
34
|
+
MULTIPART_FORM_DATA = 'multipart/form-data'
|
|
35
|
+
|
|
36
|
+
CUSTOM_HEADER_PREFIX_ROSETTE = /^X-RosetteAPI-/
|
|
37
|
+
CUSTOM_HEADER_PREFIX_BABELSTREET = /^X-BabelStreetAPI-/
|
|
38
|
+
|
|
39
|
+
# Alternate API URL
|
|
12
40
|
attr_reader :alternate_url
|
|
13
|
-
#
|
|
41
|
+
# API HTTP client
|
|
14
42
|
attr_reader :http_client
|
|
15
43
|
# Parameters to build the body of the request from
|
|
16
44
|
attr_accessor :params
|
|
17
|
-
#
|
|
45
|
+
# API key
|
|
18
46
|
attr_accessor :user_key
|
|
19
|
-
#
|
|
47
|
+
# API binding version
|
|
20
48
|
attr_accessor :binding_version
|
|
21
49
|
# User-Agent string
|
|
22
50
|
attr_reader :user_agent
|
|
@@ -28,14 +56,14 @@ class RequestBuilder
|
|
|
28
56
|
@http_client = http_client
|
|
29
57
|
@binding_version = binding_version
|
|
30
58
|
@params = params
|
|
31
|
-
@user_agent =
|
|
59
|
+
@user_agent = "Ruby/#{binding_version}/#{RUBY_VERSION}"
|
|
32
60
|
|
|
33
61
|
return unless url_parameters
|
|
34
62
|
|
|
35
|
-
@alternate_url = @alternate_url
|
|
63
|
+
@alternate_url = "#{@alternate_url}?#{URI.encode_www_form(url_parameters)}"
|
|
36
64
|
end
|
|
37
65
|
|
|
38
|
-
# Prepares a plain POST request for
|
|
66
|
+
# Prepares a plain POST request for Analytics API.
|
|
39
67
|
#
|
|
40
68
|
# ==== Attributes
|
|
41
69
|
#
|
|
@@ -50,8 +78,8 @@ class RequestBuilder
|
|
|
50
78
|
# Not ideal. Consider switching to a different library.
|
|
51
79
|
# https://stackoverflow.com/a/11802674
|
|
52
80
|
raise RosetteAPIError.new(
|
|
53
|
-
|
|
54
|
-
|
|
81
|
+
CONNECTION_ERROR_CODE,
|
|
82
|
+
CONNECTION_ERROR_MESSAGE
|
|
55
83
|
)
|
|
56
84
|
end
|
|
57
85
|
|
|
@@ -60,30 +88,32 @@ class RequestBuilder
|
|
|
60
88
|
if custom_headers
|
|
61
89
|
keys_array = custom_headers.keys
|
|
62
90
|
keys_array.each do |key|
|
|
63
|
-
if key.to_s =~
|
|
91
|
+
if key.to_s =~ CUSTOM_HEADER_PREFIX_ROSETTE || key.to_s =~ CUSTOM_HEADER_PREFIX_BABELSTREET
|
|
64
92
|
request[key] = custom_headers[key]
|
|
65
93
|
else
|
|
66
94
|
raise RosetteAPIError.new(
|
|
67
|
-
|
|
68
|
-
|
|
95
|
+
INVALID_HEADER_CODE,
|
|
96
|
+
INVALID_HEADER_MESSAGE
|
|
69
97
|
)
|
|
70
98
|
end
|
|
71
99
|
end
|
|
72
100
|
params.delete 'customHeaders'
|
|
73
101
|
end
|
|
74
102
|
|
|
75
|
-
request[
|
|
76
|
-
request[
|
|
77
|
-
request[
|
|
78
|
-
request[
|
|
79
|
-
request[
|
|
80
|
-
request[
|
|
103
|
+
request[HEADER_API_KEY] = @user_key
|
|
104
|
+
request[HEADER_CONTENT_TYPE] = CONTENT_TYPE_JSON
|
|
105
|
+
request[HEADER_ACCEPT] = ACCEPT_JSON
|
|
106
|
+
request[HEADER_USER_AGENT] = @user_agent
|
|
107
|
+
request[HEADER_BINDING_LEGACY] = BINDING_NAME
|
|
108
|
+
request[HEADER_BINDING] = BINDING_NAME
|
|
109
|
+
request[HEADER_BINDING_VERSION_LEGACY] = @binding_version
|
|
110
|
+
request[HEADER_BINDING_VERSION] = @binding_version
|
|
81
111
|
request.body = params.to_json
|
|
82
112
|
|
|
83
113
|
[@http_client, request]
|
|
84
114
|
end
|
|
85
115
|
|
|
86
|
-
# Prepares a multipart/form-data POST request for
|
|
116
|
+
# Prepares a multipart/form-data POST request for Analytics API.
|
|
87
117
|
#
|
|
88
118
|
# ==== Attributes
|
|
89
119
|
#
|
|
@@ -91,29 +121,25 @@ class RequestBuilder
|
|
|
91
121
|
#
|
|
92
122
|
# Returns a HTTP connection and the built POST request.
|
|
93
123
|
def prepare_multipart_request(params)
|
|
94
|
-
|
|
95
|
-
file = File.open params['filePath'], 'r'
|
|
96
|
-
text = file.read
|
|
97
|
-
rescue StandardError => e
|
|
98
|
-
raise RosetteAPIError.new('readMultipartError', e)
|
|
99
|
-
end
|
|
124
|
+
text = read_multipart_file params['filePath']
|
|
100
125
|
|
|
101
126
|
boundary = SecureRandom.hex
|
|
102
127
|
post_body = []
|
|
103
|
-
params.delete 'filePath'
|
|
104
|
-
request_file = params.to_json
|
|
105
128
|
|
|
106
129
|
# Add the content data
|
|
107
130
|
post_body << "--#{boundary}\r\n"
|
|
108
131
|
post_body << 'Content-Disposition: form-data; name="content"; ' \
|
|
109
|
-
"filename=\"#{File.basename(
|
|
110
|
-
post_body << "
|
|
132
|
+
"filename=\"#{File.basename(params['filePath'])}\"\r\n"
|
|
133
|
+
post_body << "#{HEADER_CONTENT_TYPE}: #{CONTENT_TYPE_TEXT_PLAIN}\r\n\r\n"
|
|
111
134
|
post_body << text
|
|
112
135
|
|
|
113
136
|
# Add the request data
|
|
137
|
+
params.delete 'filePath'
|
|
138
|
+
request_file = params.to_json
|
|
139
|
+
|
|
114
140
|
post_body << "\r\n\r\n--#{boundary}\r\n"
|
|
115
141
|
post_body << "Content-Disposition: form-data; name=\"request\"\r\n"
|
|
116
|
-
post_body << "
|
|
142
|
+
post_body << "#{HEADER_CONTENT_TYPE}: #{CONTENT_TYPE_JSON}\r\n\r\n"
|
|
117
143
|
post_body << request_file
|
|
118
144
|
post_body << "\r\n\r\n--#{boundary}--\r\n"
|
|
119
145
|
|
|
@@ -125,8 +151,8 @@ class RequestBuilder
|
|
|
125
151
|
# Not ideal. Consider switching to a different library.
|
|
126
152
|
# https://stackoverflow.com/a/11802674
|
|
127
153
|
raise RosetteAPIError.new(
|
|
128
|
-
|
|
129
|
-
|
|
154
|
+
CONNECTION_ERROR_CODE,
|
|
155
|
+
CONNECTION_ERROR_MESSAGE
|
|
130
156
|
)
|
|
131
157
|
end
|
|
132
158
|
|
|
@@ -134,30 +160,43 @@ class RequestBuilder
|
|
|
134
160
|
unless params['customHeaders'].nil?
|
|
135
161
|
keys_array = params['customHeaders'].keys
|
|
136
162
|
keys_array.each do |k|
|
|
137
|
-
if k.to_s =~
|
|
163
|
+
if k.to_s =~ CUSTOM_HEADER_PREFIX_ROSETTE || k.to_s =~ CUSTOM_HEADER_PREFIX_BABELSTREET
|
|
138
164
|
request.add_field k, params['customHeaders'][k]
|
|
139
165
|
else
|
|
140
166
|
raise RosetteAPIError.new(
|
|
141
|
-
|
|
142
|
-
|
|
167
|
+
INVALID_HEADER_CODE,
|
|
168
|
+
INVALID_HEADER_MESSAGE
|
|
143
169
|
)
|
|
144
170
|
end
|
|
145
171
|
end
|
|
146
172
|
params.delete 'customHeaders'
|
|
147
173
|
end
|
|
148
174
|
|
|
149
|
-
request.add_field
|
|
150
|
-
"
|
|
151
|
-
request.add_field
|
|
152
|
-
request.add_field
|
|
153
|
-
request.add_field
|
|
154
|
-
request.add_field
|
|
175
|
+
request.add_field HEADER_CONTENT_TYPE,
|
|
176
|
+
"#{MULTIPART_FORM_DATA}; boundary=#{boundary}"
|
|
177
|
+
request.add_field HEADER_USER_AGENT, @user_agent
|
|
178
|
+
request.add_field HEADER_API_KEY, @user_key
|
|
179
|
+
request.add_field HEADER_BINDING_LEGACY, BINDING_NAME
|
|
180
|
+
request.add_field HEADER_BINDING, BINDING_NAME
|
|
181
|
+
request.add_field HEADER_BINDING_VERSION_LEGACY, @binding_version
|
|
182
|
+
request.add_field HEADER_BINDING_VERSION, @binding_version
|
|
155
183
|
request.body = post_body.join
|
|
156
184
|
|
|
157
185
|
[@http_client, request]
|
|
158
186
|
end
|
|
159
187
|
|
|
160
|
-
#
|
|
188
|
+
# Reads the content of a file given its path.
|
|
189
|
+
#
|
|
190
|
+
# Returns the content of the file or raises error if encountered.
|
|
191
|
+
def read_multipart_file(file_path)
|
|
192
|
+
File.open(file_path, 'r') do |f|
|
|
193
|
+
return f.read
|
|
194
|
+
end
|
|
195
|
+
rescue StandardError => e
|
|
196
|
+
raise RosetteAPIError.new(READ_MULTIPART_ERROR_CODE, e)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Sends a GET request to Analytics API.
|
|
161
200
|
#
|
|
162
201
|
# Returns JSON response or raises RosetteAPIError if encountered.
|
|
163
202
|
def send_get_request
|
|
@@ -168,17 +207,17 @@ class RequestBuilder
|
|
|
168
207
|
# Not ideal. Consider switching to a different library.
|
|
169
208
|
# https://stackoverflow.com/a/11802674
|
|
170
209
|
raise RosetteAPIError.new(
|
|
171
|
-
|
|
172
|
-
|
|
210
|
+
CONNECTION_ERROR_CODE,
|
|
211
|
+
CONNECTION_ERROR_MESSAGE
|
|
173
212
|
)
|
|
174
213
|
end
|
|
175
|
-
request[
|
|
176
|
-
request[
|
|
214
|
+
request[HEADER_API_KEY] = @user_key
|
|
215
|
+
request[HEADER_USER_AGENT] = @user_agent
|
|
177
216
|
|
|
178
217
|
get_response @http_client, request
|
|
179
218
|
end
|
|
180
219
|
|
|
181
|
-
# Sends a POST request to
|
|
220
|
+
# Sends a POST request to Analytics API.
|
|
182
221
|
#
|
|
183
222
|
# Returns JSON response or raises RosetteAPIError if encountered.
|
|
184
223
|
def send_post_request
|
|
@@ -197,22 +236,23 @@ class RequestBuilder
|
|
|
197
236
|
#
|
|
198
237
|
# * +http+ - HTTP connection.
|
|
199
238
|
#
|
|
200
|
-
# * +request+ - Prepared
|
|
239
|
+
# * +request+ - Prepared API request.
|
|
201
240
|
#
|
|
202
241
|
# Returns JSON response or raises RosetteAPIError if encountered.
|
|
203
242
|
def get_response(http, request)
|
|
204
243
|
response = http.request request
|
|
205
244
|
|
|
206
|
-
if response.code
|
|
207
|
-
message = JSON.parse(response.body)['message']
|
|
208
|
-
code = JSON.parse(response.body)['code']
|
|
209
|
-
raise RosetteAPIError.new code, message
|
|
210
|
-
else
|
|
245
|
+
if response.code == '200'
|
|
211
246
|
response_headers = {}
|
|
212
247
|
response.header.each_header { |key, value| response_headers[key] = value }
|
|
213
248
|
response_headers = { responseHeaders: response_headers }
|
|
214
249
|
|
|
215
250
|
JSON.parse(response.body).merge(response_headers)
|
|
251
|
+
else
|
|
252
|
+
parsed_body = JSON.parse(response.body)
|
|
253
|
+
message = parsed_body['message']
|
|
254
|
+
code = parsed_body['code']
|
|
255
|
+
raise RosetteAPIError.new code, message
|
|
216
256
|
end
|
|
217
257
|
end
|
|
218
258
|
end
|