ibm_watson 0.13.0 → 0.14.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.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ibm_watson
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Nussbaum
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-03-13 00:00:00.000000000 Z
11
+ date: 2019-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 4.1.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: ibm_cloud_sdk_core
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.1.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.1.1
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: bundler
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -248,9 +262,7 @@ files:
248
262
  - lib/ibm_watson/assistant_v2.rb
249
263
  - lib/ibm_watson/common.rb
250
264
  - lib/ibm_watson/compare_comply_v1.rb
251
- - lib/ibm_watson/detailed_response.rb
252
265
  - lib/ibm_watson/discovery_v1.rb
253
- - lib/ibm_watson/iam_token_manager.rb
254
266
  - lib/ibm_watson/language_translator_v3.rb
255
267
  - lib/ibm_watson/natural_language_classifier_v1.rb
256
268
  - lib/ibm_watson/natural_language_understanding_v1.rb
@@ -260,8 +272,6 @@ files:
260
272
  - lib/ibm_watson/tone_analyzer_v3.rb
261
273
  - lib/ibm_watson/version.rb
262
274
  - lib/ibm_watson/visual_recognition_v3.rb
263
- - lib/ibm_watson/watson_api_exception.rb
264
- - lib/ibm_watson/watson_service.rb
265
275
  - lib/ibm_watson/websocket/recognize_callback.rb
266
276
  - lib/ibm_watson/websocket/speech_to_text_websocket_listener.rb
267
277
  - rakefile
@@ -285,7 +295,6 @@ files:
285
295
  - test/unit/test_compare_comply_v1.rb
286
296
  - test/unit/test_configure_http_client.rb
287
297
  - test/unit/test_discovery_v1.rb
288
- - test/unit/test_iam_token_manager.rb
289
298
  - test/unit/test_language_translator_v3.rb
290
299
  - test/unit/test_natural_language_classifier_v1.rb
291
300
  - test/unit/test_natural_language_understanding_v1.rb
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require("json")
4
-
5
- # Custom class for objects returned from API calls
6
- class DetailedResponse
7
- attr_reader :status, :headers, :result
8
- def initialize(status: nil, headers: nil, body: nil, response: nil)
9
- if status.nil? || headers.nil? || body.nil?
10
- @status = response.code
11
- @headers = response.headers.to_h
12
- @headers = response.headers.to_hash if response.headers.respond_to?("to_hash")
13
- @result = response.body.to_s
14
- @result = JSON.parse(response.body.to_s) if !response.body.to_s.empty? && @headers.key?("Content-Type") && @headers["Content-Type"].start_with?("application/json")
15
- else
16
- @status = status
17
- @headers = headers
18
- @result = body
19
- end
20
- end
21
- end
@@ -1,152 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require("http")
4
- require("json")
5
- require("rbconfig")
6
- require_relative("./version.rb")
7
-
8
- # Class to manage IAM Token Authentication
9
- class IAMTokenManager
10
- DEFAULT_IAM_URL = "https://iam.bluemix.net/identity/token"
11
- CONTENT_TYPE = "application/x-www-form-urlencoded"
12
- ACCEPT = "application/json"
13
- DEFAULT_AUTHORIZATION = "Basic Yng6Yng="
14
- REQUEST_TOKEN_GRANT_TYPE = "urn:ibm:params:oauth:grant-type:apikey"
15
- REQUEST_TOKEN_RESPONSE_TYPE = "cloud_iam"
16
- REFRESH_TOKEN_GRANT_TYPE = "refresh_token"
17
-
18
- attr_accessor :token_info, :user_access_token
19
- def initialize(iam_apikey: nil, iam_access_token: nil, iam_url: nil)
20
- @iam_apikey = iam_apikey
21
- @user_access_token = iam_access_token
22
- @iam_url = iam_url.nil? ? DEFAULT_IAM_URL : iam_url
23
- @token_info = {
24
- "access_token" => nil,
25
- "refresh_token" => nil,
26
- "token_type" => nil,
27
- "expires_in" => nil,
28
- "expiration" => nil
29
- }
30
- end
31
-
32
- def request(method:, url:, headers: nil, params: nil, data: nil)
33
- user_agent_string = "watson-apis-ruby-sdk-" + IBMWatson::VERSION
34
- user_agent_string += " #{RbConfig::CONFIG["host"]}"
35
- user_agent_string += " #{RbConfig::CONFIG["RUBY_BASE_NAME"]}-#{RbConfig::CONFIG["RUBY_PROGRAM_VERSION"]}"
36
- headers["User-Agent"] = user_agent_string
37
- response = nil
38
- if headers.key?("Content-Type") && headers["Content-Type"] == CONTENT_TYPE
39
- response = HTTP.request(
40
- method,
41
- url,
42
- body: HTTP::URI.form_encode(data),
43
- headers: headers,
44
- params: params
45
- )
46
- end
47
- return JSON.parse(response.body.to_s) if (200..299).cover?(response.code)
48
-
49
- require_relative("./watson_api_exception.rb")
50
- raise WatsonApiException.new(response: response)
51
- end
52
-
53
- # The source of the token is determined by the following logic:
54
- # 1. If user provides their own managed access token, assume it is valid and send it
55
- # 2. If this class is managing tokens and does not yet have one, make a request for one
56
- # 3. If this class is managing tokens and the token has expired refresh it. In case the refresh token is expired, get a new one
57
- # If this class is managing tokens and has a valid token stored, send it
58
- def token
59
- return @user_access_token unless @user_access_token.nil? || (@user_access_token.respond_to?(:empty?) && @user_access_token.empty?)
60
-
61
- if @token_info.all? { |_k, v| v.nil? }
62
- token_info = request_token
63
- save_token_info(
64
- token_info: token_info
65
- )
66
- return @token_info["access_token"]
67
- elsif token_expired?
68
- token_info = refresh_token_expired? ? request_token : refresh_token
69
- save_token_info(
70
- token_info: token_info
71
- )
72
- return @token_info["access_token"]
73
- else
74
- @token_info["access_token"]
75
- end
76
- end
77
-
78
- private
79
-
80
- # Request an IAM token using an API key
81
- def request_token
82
- headers = {
83
- "Content-Type" => CONTENT_TYPE,
84
- "Authorization" => DEFAULT_AUTHORIZATION,
85
- "Accept" => ACCEPT
86
- }
87
- data = {
88
- "grant_type" => REQUEST_TOKEN_GRANT_TYPE,
89
- "apikey" => @iam_apikey,
90
- "response_type" => REQUEST_TOKEN_RESPONSE_TYPE
91
- }
92
- response = request(
93
- method: "POST",
94
- url: @iam_url,
95
- headers: headers,
96
- data: data
97
- )
98
- response
99
- end
100
-
101
- # Refresh an IAM token using a refresh token
102
- def refresh_token
103
- headers = {
104
- "Content-Type" => CONTENT_TYPE,
105
- "Authorization" => DEFAULT_AUTHORIZATION,
106
- "accept" => ACCEPT
107
- }
108
- data = {
109
- "grant_type" => REFRESH_TOKEN_GRANT_TYPE,
110
- "refresh_token" => @token_info["refresh_token"]
111
- }
112
- response = request(
113
- method: "POST",
114
- url: @iam_url,
115
- headers: headers,
116
- data: data
117
- )
118
- response
119
- end
120
-
121
- # Check if currently stored token is expired.
122
- # Using a buffer to prevent the edge case of the
123
- # token expiring before the request could be made.
124
- # The buffer will be a fraction of the total TTL. Using 80%.
125
- def token_expired?
126
- return true if @token_info["expiration"].nil? || @token_info["expires_in"].nil?
127
-
128
- fraction_of_ttl = 0.8
129
- time_to_live = @token_info["expires_in"].nil? ? 0 : @token_info["expires_in"]
130
- expire_time = @token_info["expiration"].nil? ? 0 : @token_info["expiration"]
131
- refresh_time = expire_time - (time_to_live * (1.0 - fraction_of_ttl))
132
- current_time = Time.now.to_i
133
- refresh_time < current_time
134
- end
135
-
136
- # Used as a fail-safe to prevent the condition of a refresh token expiring,
137
- # which could happen after around 30 days. This function will return true
138
- # if it has been at least 7 days and 1 hour since the last token was set
139
- def refresh_token_expired?
140
- return true if @token_info["expiration"].nil?
141
-
142
- seven_days = 7 * 24 * 3600
143
- current_time = Time.now.to_i
144
- new_token_time = @token_info["expiration"] + seven_days
145
- new_token_time < current_time
146
- end
147
-
148
- # Save the response from the IAM service request to the object's state
149
- def save_token_info(token_info:)
150
- @token_info = token_info
151
- end
152
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require("json")
4
- # Custom exception class for errors returned from Watson APIs
5
- class WatsonApiException < StandardError
6
- attr_reader :code, :error, :info, :transaction_id, :global_transaction_id
7
- # :param HTTP::Response response: The response object from the Watson API
8
- def initialize(code: nil, error: nil, info: nil, transaction_id: nil, global_transaction_id: nil, response: nil)
9
- if code.nil? || error.nil?
10
- @code = response.code
11
- @error = response.reason
12
- unless response.body.empty?
13
- body_hash = JSON.parse(response.body.to_s)
14
- @code = body_hash["code"] || body_hash["error_code"] || body_hash["status"]
15
- @error = body_hash["error"] || body_hash["error_message"] || body_hash["statusInfo"] || body_hash["description"]
16
- %w[code error_code status error error_message statusInfo description].each { |k| body_hash.delete(k) }
17
- @info = body_hash
18
- end
19
- @transaction_id = transaction_id
20
- @global_transaction_id = global_transaction_id
21
- @transaction_id = response.headers["X-DP-Watson-Tran-ID"] if response.headers.include?("X-DP-Watson-Tran-ID")
22
- @global_transaction_id = response.headers["X-Global-Transaction-ID"] if response.headers.include?("X-Global-Transaction-ID")
23
- else
24
- # :nocov:
25
- @code = code
26
- @error = error
27
- @info = info
28
- @transaction_id = transaction_id
29
- @global_transaction_id = global_transaction_id
30
- # :nocov:
31
- end
32
- end
33
-
34
- def to_s
35
- msg = "Error: #{@error}, Code: #{@code}"
36
- msg += ", Information: #{@info}" unless @info.nil?
37
- msg += ", X-dp-watson-tran-id: #{@transaction_id}" unless @transaction_id.nil?
38
- msg += ", X-global-transaction-id: #{@global_transaction_id}" unless @global_transaction_id.nil?
39
- msg
40
- end
41
- end
@@ -1,285 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require("http")
4
- require("rbconfig")
5
- require("stringio")
6
- require("json")
7
- require_relative("./detailed_response.rb")
8
- require_relative("./watson_api_exception.rb")
9
- require_relative("./iam_token_manager.rb")
10
- require_relative("./version.rb")
11
- require_relative("./common.rb")
12
- # require("httplog")
13
- # HttpLog.configure do |config|
14
- # config.log_connect = true
15
- # config.log_request = true
16
- # config.log_headers = true
17
- # config.log_data = true
18
- # config.log_status = true
19
- # config.log_response = true
20
- # end
21
-
22
- DEFAULT_CREDENTIALS_FILE_NAME = "ibm-credentials.env"
23
- NORMALIZER = lambda do |uri| # Custom URI normalizer when using HTTP Client
24
- HTTP::URI.parse uri
25
- end
26
-
27
- # Class for interacting with the Watson API
28
- class WatsonService
29
- attr_accessor :password, :url, :username, :display_name
30
- attr_reader :conn, :token_manager
31
- def initialize(vars)
32
- defaults = {
33
- vcap_services_name: nil,
34
- username: nil,
35
- password: nil,
36
- use_vcap_services: true,
37
- iam_apikey: nil,
38
- iam_access_token: nil,
39
- iam_url: nil,
40
- display_name: nil
41
- }
42
- vars = defaults.merge(vars)
43
- @url = vars[:url]
44
- @username = nil
45
- @password = nil
46
- @iam_apikey = nil
47
- @token_manager = nil
48
- @temp_headers = nil
49
- @icp_prefix = vars[:password]&.start_with?("icp-") ? true : false
50
- @disable_ssl = false
51
- @display_name = vars[:display_name]
52
-
53
- if !vars[:iam_access_token].nil? || !vars[:iam_apikey].nil?
54
- set_token_manager(iam_apikey: vars[:iam_apikey], iam_access_token: vars[:iam_access_token], iam_url: vars[:iam_url])
55
- elsif !vars[:username].nil? && !vars[:password].nil?
56
- if vars[:username] == "apikey" && !@icp_prefix
57
- iam_apikey(iam_apikey: vars[:password])
58
- else
59
- @username = vars[:username]
60
- @password = vars[:password]
61
- end
62
- end
63
-
64
- if @display_name && !@username && !@iam_apikey
65
- service_name = @display_name.sub(" ", "_").downcase
66
- load_from_credential_file(service_name)
67
- end
68
-
69
- if vars[:use_vcap_services] && !@username && !@iam_apikey
70
- @vcap_service_credentials = load_from_vcap_services(service_name: vars[:vcap_services_name])
71
- if !@vcap_service_credentials.nil? && @vcap_service_credentials.instance_of?(Hash)
72
- @url = @vcap_service_credentials["url"]
73
- @username = @vcap_service_credentials["username"] if @vcap_service_credentials.key?("username")
74
- @password = @vcap_service_credentials["password"] if @vcap_service_credentials.key?("password")
75
- @iam_apikey = @vcap_service_credentials["iam_apikey"] if @vcap_service_credentials.key?("iam_apikey")
76
- @iam_access_token = @vcap_service_credentials["iam_access_token"] if @vcap_service_credentials.key?("iam_access_token")
77
- @iam_url = @vcap_service_credentials["iam_url"] if @vcap_service_credentials.key?("iam_url")
78
- end
79
- end
80
-
81
- raise ArgumentError.new('The username shouldn\'t start or end with curly brackets or quotes. Be sure to remove any {} and \" characters surrounding your username') if check_bad_first_or_last_char(@username)
82
- raise ArgumentError.new('The password shouldn\'t start or end with curly brackets or quotes. Be sure to remove any {} and \" characters surrounding your password') if check_bad_first_or_last_char(@password)
83
- raise ArgumentError.new('The url shouldn\'t start or end with curly brackets or quotes. Be sure to remove any {} and \" characters surrounding your url') if check_bad_first_or_last_char(@url)
84
- raise ArgumentError.new('The apikey shouldn\'t start or end with curly brackets or quotes. Be sure to remove any {} and \" characters surrounding your apikey') if check_bad_first_or_last_char(@iam_apikey)
85
-
86
- @conn = HTTP::Client.new(
87
- headers: {}
88
- ).use normalize_uri: { normalizer: NORMALIZER }
89
- end
90
-
91
- # Initiates the credentials based on the credential file
92
- def load_from_credential_file(service_name, separator = "=")
93
- credential_file_path = ENV["IBM_CREDENTIALS_FILE"]
94
-
95
- # Home directory
96
- if credential_file_path.nil?
97
- file_path = ENV["HOME"] + DEFAULT_CREDENTIALS_FILE_NAME
98
- credential_file_path = file_path if File.exist?(file_path)
99
- end
100
-
101
- # Top-level directory of the project
102
- if credential_file_path.nil?
103
- file_path = File.join(File.dirname(__FILE__), "/../../" + DEFAULT_CREDENTIALS_FILE_NAME)
104
- credential_file_path = file_path if File.exist?(file_path)
105
- end
106
-
107
- return if credential_file_path.nil?
108
-
109
- file_contents = File.open(credential_file_path, "r")
110
- file_contents.each_line do |line|
111
- key_val = line.strip.split(separator)
112
- set_credential_based_on_type(service_name, key_val[0].downcase, key_val[1].downcase) if key_val.length == 2
113
- end
114
- end
115
-
116
- def load_from_vcap_services(service_name:)
117
- vcap_services = ENV["VCAP_SERVICES"]
118
- unless vcap_services.nil?
119
- services = JSON.parse(vcap_services)
120
- return services[service_name][0]["credentials"] if services.key?(service_name)
121
- end
122
- nil
123
- end
124
-
125
- def add_default_headers(headers: {})
126
- raise TypeError unless headers.instance_of?(Hash)
127
-
128
- headers.each_pair { |k, v| @conn.default_options.headers.add(k, v) }
129
- end
130
-
131
- def iam_access_token(iam_access_token:)
132
- @token_manager = IAMTokenManager.new(iam_access_token: iam_access_token) if @token_manager.nil?
133
- @iam_access_token = iam_access_token
134
- end
135
-
136
- def iam_apikey(iam_apikey:)
137
- @token_manager = IAMTokenManager.new(iam_apikey: iam_apikey) if @token_manager.nil?
138
- @iam_apikey = iam_apikey
139
- end
140
-
141
- # @return [DetailedResponse]
142
- def request(args)
143
- defaults = { method: nil, url: nil, accept_json: false, headers: nil, params: nil, json: {}, data: nil }
144
- args = defaults.merge(args)
145
- args[:data].delete_if { |_k, v| v.nil? } if args[:data].instance_of?(Hash)
146
- args[:json] = args[:data].merge(args[:json]) if args[:data].respond_to?(:merge)
147
- args[:json] = args[:data] if args[:json].empty? || (args[:data].instance_of?(String) && !args[:data].empty?)
148
- args[:json].delete_if { |_k, v| v.nil? } if args[:json].instance_of?(Hash)
149
- args[:headers]["Accept"] = "application/json" if args[:accept_json] && args[:headers]["Accept"].nil?
150
- args[:headers]["Content-Type"] = "application/json" unless args[:headers].key?("Content-Type")
151
- args[:json] = args[:json].to_json if args[:json].instance_of?(Hash)
152
- args[:headers].delete_if { |_k, v| v.nil? } if args[:headers].instance_of?(Hash)
153
- args[:params].delete_if { |_k, v| v.nil? } if args[:params].instance_of?(Hash)
154
- args[:form].delete_if { |_k, v| v.nil? } if args.key?(:form)
155
- args.delete_if { |_, v| v.nil? }
156
- args[:headers].delete("Content-Type") if args.key?(:form) || args[:json].nil?
157
-
158
- if @username == "apikey" && !@icp_prefix
159
- iam_apikey(iam_apikey: @password)
160
- @username = nil
161
- end
162
-
163
- conn = @conn
164
- if !@token_manager.nil?
165
- access_token = @token_manager.token
166
- args[:headers]["Authorization"] = "Bearer #{access_token}"
167
- elsif !@username.nil? && !@password.nil?
168
- conn = @conn.basic_auth(user: @username, pass: @password)
169
- end
170
-
171
- args[:headers] = args[:headers].merge(@temp_headers) unless @temp_headers.nil?
172
- @temp_headers = nil unless @temp_headers.nil?
173
-
174
- if args.key?(:form)
175
- response = conn.follow.request(
176
- args[:method],
177
- HTTP::URI.parse(@url + args[:url]),
178
- headers: conn.default_options.headers.merge(HTTP::Headers.coerce(args[:headers])),
179
- params: args[:params],
180
- form: args[:form]
181
- )
182
- else
183
- response = conn.follow.request(
184
- args[:method],
185
- HTTP::URI.parse(@url + args[:url]),
186
- headers: conn.default_options.headers.merge(HTTP::Headers.coerce(args[:headers])),
187
- body: args[:json],
188
- params: args[:params]
189
- )
190
- end
191
- return DetailedResponse.new(response: response) if (200..299).cover?(response.code)
192
-
193
- raise WatsonApiException.new(response: response)
194
- end
195
-
196
- # @note Chainable
197
- # @param headers [Hash] Custom headers to be sent with the request
198
- # @return [self]
199
- def headers(headers)
200
- raise TypeError("Expected Hash type, received #{headers.class}") unless headers.instance_of?(Hash)
201
-
202
- @temp_headers = headers
203
- self
204
- end
205
-
206
- # @!method configure_http_client(proxy: {}, timeout: {}, disable_ssl: false)
207
- # Sets the http client config, currently works with timeout and proxies
208
- # @param proxy [Hash] The hash of proxy configurations
209
- # @option proxy address [String] The address of the proxy
210
- # @option proxy port [Integer] The port of the proxy
211
- # @option proxy username [String] The username of the proxy, if authentication is needed
212
- # @option proxy password [String] The password of the proxy, if authentication is needed
213
- # @option proxy headers [Hash] The headers to be used with the proxy
214
- # @param timeout [Hash] The hash for configuring timeouts. `per_operation` has priority over `global`
215
- # @option timeout per_operation [Hash] Timeouts per operation. Requires `read`, `write`, `connect`
216
- # @option timeout global [Integer] Upper bound on total request time
217
- # @param disable_ssl [Boolean] Disable the SSL verification (Note that this has serious security implications - only do this if you really mean to!)
218
- def configure_http_client(proxy: {}, timeout: {}, disable_ssl: false)
219
- raise TypeError("proxy parameter must be a Hash") unless proxy.empty? || proxy.instance_of?(Hash)
220
-
221
- raise TypeError("timeout parameter must be a Hash") unless timeout.empty? || timeout.instance_of?(Hash)
222
-
223
- @disable_ssl = disable_ssl
224
- if disable_ssl
225
- ssl_context = OpenSSL::SSL::SSLContext.new
226
- ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
227
- @conn.default_options = { ssl_context: ssl_context }
228
- end
229
- add_proxy(proxy) unless proxy.empty? || !proxy.dig(:address).is_a?(String) || !proxy.dig(:port).is_a?(Integer)
230
- add_timeout(timeout) unless timeout.empty? || (!timeout.key?(:per_operation) && !timeout.key?(:global))
231
- end
232
-
233
- private
234
-
235
- def set_credential_based_on_type(service_name, key, value)
236
- return unless key.include?(service_name)
237
-
238
- @iam_apikey = value if key.include?("iam_apikey")
239
- @iam_url = value if key.include?("iam_url")
240
- @url = value if key.include?("url")
241
- @username = value if key.include?("username")
242
- @password = value if key.include?("password")
243
- end
244
-
245
- def check_bad_first_or_last_char(str)
246
- return str.start_with?("{", "\"") || str.end_with?("}", "\"") unless str.nil?
247
- end
248
-
249
- def set_token_manager(iam_apikey: nil, iam_access_token: nil, iam_url: nil)
250
- @iam_apikey = iam_apikey
251
- @iam_access_token = iam_access_token
252
- @iam_url = iam_url
253
- @token_manager = IAMTokenManager.new(iam_apikey: iam_apikey, iam_access_token: iam_access_token, iam_url: iam_url)
254
- end
255
-
256
- def add_timeout(timeout)
257
- if timeout.key?(:per_operation)
258
- raise TypeError("per_operation in timeout must be a Hash") unless timeout[:per_operation].instance_of?(Hash)
259
-
260
- defaults = {
261
- write: 0,
262
- connect: 0,
263
- read: 0
264
- }
265
- time = defaults.merge(timeout[:per_operation])
266
- @conn = @conn.timeout(write: time[:write], connect: time[:connect], read: time[:read])
267
- else
268
- raise TypeError("global in timeout must be an Integer") unless timeout[:global].is_a?(Integer)
269
-
270
- @conn = @conn.timeout(timeout[:global])
271
- end
272
- end
273
-
274
- def add_proxy(proxy)
275
- if (proxy[:username].nil? || proxy[:password].nil?) && proxy[:headers].nil?
276
- @conn = @conn.via(proxy[:address], proxy[:port])
277
- elsif !proxy[:username].nil? && !proxy[:password].nil? && proxy[:headers].nil?
278
- @conn = @conn.via(proxy[:address], proxy[:port], proxy[:username], proxy[:password])
279
- elsif !proxy[:headers].nil? && (proxy[:username].nil? || proxy[:password].nil?)
280
- @conn = @conn.via(proxy[:address], proxy[:port], proxy[:headers])
281
- else
282
- @conn = @conn.via(proxy[:address], proxy[:port], proxy[:username], proxy[:password], proxy[:headers])
283
- end
284
- end
285
- end