plivo 0.3.19 → 4.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.travis.yml +11 -0
- data/AUTHORS.md +4 -0
- data/CHANGELOG.md +158 -0
- data/Gemfile +10 -0
- data/Jenkinsfile +7 -0
- data/LICENSE.txt +19 -0
- data/README.md +155 -24
- data/Rakefile +9 -0
- data/ci/config.yml +7 -0
- data/examples/conference_bridge.rb +108 -0
- data/examples/jwt.rb +32 -0
- data/examples/lookup.rb +24 -0
- data/examples/multi_party_call.rb +295 -0
- data/examples/phlos.rb +55 -0
- data/examples/regulatory_compliance.rb +167 -0
- data/lib/plivo/base/resource.rb +148 -0
- data/lib/plivo/base/resource_interface.rb +108 -0
- data/lib/plivo/base/response.rb +38 -0
- data/lib/plivo/base.rb +17 -0
- data/lib/plivo/base_client.rb +393 -0
- data/lib/plivo/exceptions.rb +50 -0
- data/lib/plivo/jwt.rb +120 -0
- data/lib/plivo/phlo_client.rb +29 -0
- data/lib/plivo/resources/accounts.rb +181 -0
- data/lib/plivo/resources/addresses.rb +302 -0
- data/lib/plivo/resources/applications.rb +258 -0
- data/lib/plivo/resources/call_feedback.rb +55 -0
- data/lib/plivo/resources/calls.rb +559 -0
- data/lib/plivo/resources/conferences.rb +367 -0
- data/lib/plivo/resources/endpoints.rb +132 -0
- data/lib/plivo/resources/identities.rb +319 -0
- data/lib/plivo/resources/lookup.rb +88 -0
- data/lib/plivo/resources/media.rb +97 -0
- data/lib/plivo/resources/messages.rb +215 -0
- data/lib/plivo/resources/multipartycalls.rb +554 -0
- data/lib/plivo/resources/nodes.rb +83 -0
- data/lib/plivo/resources/numbers.rb +319 -0
- data/lib/plivo/resources/phlo_member.rb +64 -0
- data/lib/plivo/resources/phlos.rb +55 -0
- data/lib/plivo/resources/powerpacks.rb +717 -0
- data/lib/plivo/resources/pricings.rb +43 -0
- data/lib/plivo/resources/recordings.rb +116 -0
- data/lib/plivo/resources/regulatory_compliance.rb +610 -0
- data/lib/plivo/resources.rb +25 -0
- data/lib/plivo/rest_client.rb +63 -0
- data/lib/plivo/utils.rb +294 -0
- data/lib/plivo/version.rb +3 -0
- data/lib/plivo/xml/break.rb +31 -0
- data/lib/plivo/xml/conference.rb +20 -0
- data/lib/plivo/xml/cont.rb +13 -0
- data/lib/plivo/xml/dial.rb +16 -0
- data/lib/plivo/xml/dtmf.rb +13 -0
- data/lib/plivo/xml/element.rb +106 -0
- data/lib/plivo/xml/emphasis.rb +17 -0
- data/lib/plivo/xml/get_digits.rb +15 -0
- data/lib/plivo/xml/get_input.rb +16 -0
- data/lib/plivo/xml/hangup.rb +12 -0
- data/lib/plivo/xml/lang.rb +29 -0
- data/lib/plivo/xml/message.rb +13 -0
- data/lib/plivo/xml/multipartycall.rb +188 -0
- data/lib/plivo/xml/number.rb +13 -0
- data/lib/plivo/xml/p.rb +12 -0
- data/lib/plivo/xml/phoneme.rb +20 -0
- data/lib/plivo/xml/play.rb +13 -0
- data/lib/plivo/xml/plivo_xml.rb +19 -0
- data/lib/plivo/xml/pre_answer.rb +12 -0
- data/lib/plivo/xml/prosody.rb +28 -0
- data/lib/plivo/xml/record.rb +17 -0
- data/lib/plivo/xml/redirect.rb +13 -0
- data/lib/plivo/xml/response.rb +21 -0
- data/lib/plivo/xml/s.rb +12 -0
- data/lib/plivo/xml/say_as.rb +24 -0
- data/lib/plivo/xml/speak.rb +28 -0
- data/lib/plivo/xml/sub.rb +16 -0
- data/lib/plivo/xml/user.rb +13 -0
- data/lib/plivo/xml/w.rb +17 -0
- data/lib/plivo/xml/wait.rb +12 -0
- data/lib/plivo/xml.rb +39 -0
- data/lib/plivo.rb +12 -815
- data/plivo.gemspec +44 -0
- metadata +181 -41
- data/ext/mkrf_conf.rb +0 -9
@@ -0,0 +1,108 @@
|
|
1
|
+
module Plivo
|
2
|
+
module Base
|
3
|
+
class ResourceInterface
|
4
|
+
include Plivo::Utils
|
5
|
+
def initialize(client, resource_list_json = nil)
|
6
|
+
configure_client(client)
|
7
|
+
configure_resource_uri
|
8
|
+
parse_and_set(resource_list_json) if resource_list_json
|
9
|
+
@_is_voice_request = false
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def configure_client(client)
|
15
|
+
valid_param?(:client, client, [RestClient, Phlo], true)
|
16
|
+
@_client = client
|
17
|
+
end
|
18
|
+
|
19
|
+
def configure_resource_uri
|
20
|
+
to_join = ['', 'v1', 'Account', @_client.auth_id, @_name, '']
|
21
|
+
to_join = ['', 'v1', 'Account', ''] if @_name == 'Account'
|
22
|
+
to_join = ['', 'v1', @_name, ''] if @_name == 'phlo'
|
23
|
+
@_resource_uri = to_join.join('/')
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse_and_set(resource_list_json)
|
27
|
+
return unless resource_list_json
|
28
|
+
|
29
|
+
valid_param?(:resource_list_json, resource_list_json, Hash, true)
|
30
|
+
|
31
|
+
resource_list_json.each do |k, v|
|
32
|
+
if k == 'objects'
|
33
|
+
parse_and_set_list(resource_list_json['objects'])
|
34
|
+
elsif k == 'meta'
|
35
|
+
@_meta = resource_list_json['meta']
|
36
|
+
else
|
37
|
+
instance_variable_set("@#{k}", v)
|
38
|
+
self.class.send(:attr_reader, k)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def perform_get(identifier, params = nil)
|
44
|
+
valid_param?(:identifier, identifier, [String, Symbol], true)
|
45
|
+
response_json = @_client.send_request(@_resource_uri + identifier.to_s + '/', 'GET', params, nil, false, is_voice_request: @_is_voice_request)
|
46
|
+
@_resource_type.new(@_client, resource_json: response_json)
|
47
|
+
end
|
48
|
+
|
49
|
+
def perform_get_without_identifier(params)
|
50
|
+
valid_param?(:params, params, Hash, true)
|
51
|
+
response_json = @_client.send_request(@_resource_uri, 'GET', params, nil, false, is_voice_request: @_is_voice_request)
|
52
|
+
@_resource_type.new(@_client, resource_json: response_json)
|
53
|
+
end
|
54
|
+
|
55
|
+
def perform_create(params, use_multipart_conn=false)
|
56
|
+
Response.new(
|
57
|
+
@_client.send_request(@_resource_uri, 'POST', params, nil, use_multipart_conn, is_voice_request: @_is_voice_request),
|
58
|
+
@_identifier_string
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
def perform_submit(identifier, params = nil)
|
63
|
+
valid_param?(:identifier, identifier, [String, Symbol], true)
|
64
|
+
response_json = @_client.send_request(@_resource_uri + identifier.to_s + '/Submit/', 'POST', params, nil, false, is_voice_request: @_is_voice_request)
|
65
|
+
@_resource_type.new(@_client, resource_json: response_json)
|
66
|
+
end
|
67
|
+
|
68
|
+
def perform_post(params)
|
69
|
+
response_json = @_client.send_request(@_resource_uri, 'POST', params, nil, false, is_voice_request: @_is_voice_request)
|
70
|
+
|
71
|
+
parse_and_set(response_json)
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse_and_set_list(list_json)
|
76
|
+
return unless list_json
|
77
|
+
valid_param?(:list_json, list_json, Array, false)
|
78
|
+
@_resource_list = list_json.map do |resource|
|
79
|
+
@_resource_type.new(@_client, resource_json: resource)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def perform_list(params = nil)
|
84
|
+
response_json = @_client.send_request(@_resource_uri, 'GET', params, nil, false, is_voice_request: @_is_voice_request)
|
85
|
+
parse_and_set(response_json)
|
86
|
+
{
|
87
|
+
api_id: @api_id,
|
88
|
+
meta: @_meta,
|
89
|
+
objects: @_resource_list
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def perform_action(action = nil, method = 'GET', params = nil, parse = false)
|
94
|
+
resource_path = action ? @_resource_uri + action + '/' : @_resource_uri
|
95
|
+
response = @_client.send_request(resource_path, method, params, nil, false, is_voice_request: @_is_voice_request)
|
96
|
+
parse ? parse_and_set(response) : self
|
97
|
+
method == 'POST' ? parse_and_set(params) : self
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
def perform_list_without_object(params = nil)
|
102
|
+
response_json = @_client.send_request(@_resource_uri, 'GET', params, nil, false, is_voice_request: @_is_voice_request)
|
103
|
+
parse_and_set(response_json)
|
104
|
+
response_json
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Plivo
|
2
|
+
module Base
|
3
|
+
##
|
4
|
+
# A class to provide a blanket response based on what is
|
5
|
+
# being received from Plivo servers.
|
6
|
+
#
|
7
|
+
# This will be used only during POST and DELETE requests.
|
8
|
+
class Response
|
9
|
+
##
|
10
|
+
# Instantiating a new instance requires a response_hash
|
11
|
+
# The id_symbol should contain a Symbol that represents
|
12
|
+
# the identifier of the resource for which this response
|
13
|
+
# is being generated for.
|
14
|
+
|
15
|
+
def initialize(response_hash, id_symbol = nil)
|
16
|
+
return unless response_hash
|
17
|
+
|
18
|
+
response_hash.each do |k, v|
|
19
|
+
instance_variable_set("@#{k}", v)
|
20
|
+
self.class.send(:attr_reader, k)
|
21
|
+
end
|
22
|
+
return unless id_symbol && response_hash.key?(id_symbol)
|
23
|
+
|
24
|
+
self.class.send(:attr_reader, :id)
|
25
|
+
@id = response_hash[id_symbol]
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
h = self.instance_variables.map do |attribute|
|
30
|
+
key = attribute.to_s.gsub('@','')
|
31
|
+
[key, self.instance_variable_get(attribute)]
|
32
|
+
end.to_h
|
33
|
+
h.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/plivo/base.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'base/resource_interface'
|
2
|
+
require_relative 'base/resource'
|
3
|
+
require_relative 'base/response'
|
4
|
+
|
5
|
+
module Plivo
|
6
|
+
module Base
|
7
|
+
PLIVO_API_URL = 'https://api.plivo.com'.freeze
|
8
|
+
|
9
|
+
API_VOICE = 'https://voice.plivo.com'.freeze
|
10
|
+
API_VOICE_FALLBACK_1 = 'https://voice-usw1.plivo.com'.freeze
|
11
|
+
API_VOICE_FALLBACK_2 = 'https://voice-use1.plivo.com'.freeze
|
12
|
+
|
13
|
+
CALLINSIGHTS_API_URL = 'https://stats.plivo.com'.freeze
|
14
|
+
PHLO_API_URL = 'https://phlorunner.plivo.com'.freeze
|
15
|
+
LOOKUP_API_URL = 'https://lookup.plivo.com'.freeze
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,393 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'faraday'
|
3
|
+
require 'faraday_middleware'
|
4
|
+
|
5
|
+
require_relative 'exceptions'
|
6
|
+
require_relative 'utils'
|
7
|
+
require_relative 'resources'
|
8
|
+
require_relative 'base'
|
9
|
+
|
10
|
+
module Plivo
|
11
|
+
# Core client, used for all API requests
|
12
|
+
include Utils
|
13
|
+
class BaseClient
|
14
|
+
# Base stuff
|
15
|
+
attr_reader :headers, :auth_credentials
|
16
|
+
@@voice_retry_count = 0
|
17
|
+
def initialize(auth_id = nil, auth_token = nil, proxy_options = nil, timeout=5)
|
18
|
+
configure_credentials(auth_id, auth_token)
|
19
|
+
configure_proxies(proxy_options)
|
20
|
+
configure_timeout(timeout)
|
21
|
+
configure_headers
|
22
|
+
configure_connection
|
23
|
+
end
|
24
|
+
|
25
|
+
def auth_id
|
26
|
+
@auth_credentials[:auth_id]
|
27
|
+
end
|
28
|
+
|
29
|
+
def process_response(method, response)
|
30
|
+
handle_response_exceptions(response)
|
31
|
+
if method == 'DELETE'
|
32
|
+
if !([200, 204].include? response[:status])
|
33
|
+
raise Exceptions::PlivoRESTError, "Resource at #{response[:url]} "\
|
34
|
+
'couldn\'t be deleted'
|
35
|
+
end
|
36
|
+
elsif !([200, 201, 202, 204, 207].include? response[:status])
|
37
|
+
raise Exceptions::PlivoRESTError, "Received #{response[:status]} for #{method}"
|
38
|
+
end
|
39
|
+
@@voice_retry_count = 0
|
40
|
+
response[:body]
|
41
|
+
end
|
42
|
+
|
43
|
+
def send_request(resource_path, method = 'GET', data = {}, timeout = nil, use_multipart_conn = false, options = nil)
|
44
|
+
timeout ||= @timeout
|
45
|
+
|
46
|
+
if options[:is_voice_request] == true
|
47
|
+
response = case method
|
48
|
+
when 'GET' then send_get(resource_path, data, timeout, is_voice_request: options[:is_voice_request], voice_retry_count: @@voice_retry_count)
|
49
|
+
when 'POST' then send_post(resource_path, data, timeout, use_multipart_conn, is_voice_request: options[:is_voice_request], voice_retry_count: @@voice_retry_count)
|
50
|
+
when 'DELETE' then send_delete(resource_path, data, timeout, is_voice_request: options[:is_voice_request], voice_retry_count: @@voice_retry_count)
|
51
|
+
else raise_invalid_request("#{method} not supported by Plivo, yet")
|
52
|
+
end
|
53
|
+
|
54
|
+
if response.status >= 500
|
55
|
+
@@voice_retry_count += 1
|
56
|
+
if @@voice_retry_count > 2
|
57
|
+
return process_response(method, response.to_hash)
|
58
|
+
end
|
59
|
+
is_voice_request = true
|
60
|
+
send_request(resource_path, method, data, timeout, use_multipart_conn, is_voice_request: is_voice_request)
|
61
|
+
else
|
62
|
+
process_response(method, response.to_hash)
|
63
|
+
end
|
64
|
+
elsif options[:is_lookup_request] == true
|
65
|
+
response = case method
|
66
|
+
when 'GET' then send_get(resource_path, data, timeout, is_lookup_request: options[:is_lookup_request])
|
67
|
+
else raise_invalid_request("#{method} not supported by Plivo, yet")
|
68
|
+
end
|
69
|
+
process_response(method, response.to_hash)
|
70
|
+
else
|
71
|
+
response = case method
|
72
|
+
when 'GET' then send_get(resource_path, data, timeout)
|
73
|
+
when 'POST' then send_post(resource_path, data, timeout, use_multipart_conn)
|
74
|
+
when 'DELETE' then send_delete(resource_path, data, timeout)
|
75
|
+
else raise_invalid_request("#{method} not supported by Plivo, yet")
|
76
|
+
end
|
77
|
+
|
78
|
+
process_response(method, response.to_hash)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def auth_token
|
85
|
+
@auth_credentials[:auth_token]
|
86
|
+
end
|
87
|
+
|
88
|
+
def configure_credentials(auth_id, auth_token)
|
89
|
+
# Fetches and sets the right credentials
|
90
|
+
auth_id ||= ENV['PLIVO_AUTH_ID']
|
91
|
+
auth_token ||= ENV['PLIVO_AUTH_TOKEN']
|
92
|
+
|
93
|
+
raise Exceptions::AuthenticationError, 'Couldn\'t find auth credentials' unless
|
94
|
+
auth_id && auth_token
|
95
|
+
|
96
|
+
raise Exceptions::AuthenticationError, "Invalid auth_id: '#{auth_id}'" unless
|
97
|
+
Utils.valid_account?(auth_id)
|
98
|
+
|
99
|
+
@auth_credentials = {
|
100
|
+
auth_id: auth_id,
|
101
|
+
auth_token: auth_token
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def configure_proxies(proxy_dict)
|
106
|
+
@proxy_hash = nil
|
107
|
+
return unless proxy_dict
|
108
|
+
|
109
|
+
@proxy_hash = {
|
110
|
+
uri: "#{proxy_dict[:proxy_host]}:#{proxy_dict[:proxy_port]}",
|
111
|
+
user: proxy_dict[:proxy_user],
|
112
|
+
password: proxy_dict[:proxy_pass]
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def configure_timeout(timeout)
|
117
|
+
@timeout = timeout
|
118
|
+
end
|
119
|
+
|
120
|
+
def user_agent
|
121
|
+
"plivo-ruby/#{Plivo::VERSION} (Ruby #{RUBY_VERSION})"
|
122
|
+
end
|
123
|
+
|
124
|
+
def configure_headers
|
125
|
+
@headers = {
|
126
|
+
'User-Agent' => user_agent,
|
127
|
+
'Content-Type' => 'application/json',
|
128
|
+
'Accept' => 'application/json'
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
def configure_connection
|
134
|
+
@conn = Faraday.new(@base_uri) do |faraday|
|
135
|
+
faraday.headers = @headers
|
136
|
+
|
137
|
+
# DANGER: Basic auth should always come after headers, else
|
138
|
+
# The headers will replace the basic_auth
|
139
|
+
|
140
|
+
faraday.basic_auth(auth_id, auth_token)
|
141
|
+
|
142
|
+
faraday.proxy=@proxy_hash if @proxy_hash
|
143
|
+
faraday.response :json, content_type: /\bjson$/
|
144
|
+
faraday.adapter Faraday.default_adapter
|
145
|
+
end
|
146
|
+
|
147
|
+
@voice_conn_no_retry = Faraday.new(@voice_base_uri) do |faraday|
|
148
|
+
faraday.headers = @headers
|
149
|
+
|
150
|
+
# DANGER: Basic auth should always come after headers, else
|
151
|
+
# The headers will replace the basic_auth
|
152
|
+
|
153
|
+
faraday.basic_auth(auth_id, auth_token)
|
154
|
+
|
155
|
+
faraday.proxy=@proxy_hash if @proxy_hash
|
156
|
+
faraday.response :json, content_type: /\bjson$/
|
157
|
+
faraday.adapter Faraday.default_adapter
|
158
|
+
end
|
159
|
+
|
160
|
+
@voice_conn_retry_1 = Faraday.new(@voice_base_uri_fallback_1) do |faraday|
|
161
|
+
faraday.headers = @headers
|
162
|
+
|
163
|
+
# DANGER: Basic auth should always come after headers, else
|
164
|
+
# The headers will replace the basic_auth
|
165
|
+
|
166
|
+
faraday.basic_auth(auth_id, auth_token)
|
167
|
+
|
168
|
+
faraday.proxy=@proxy_hash if @proxy_hash
|
169
|
+
faraday.response :json, content_type: /\bjson$/
|
170
|
+
faraday.adapter Faraday.default_adapter
|
171
|
+
end
|
172
|
+
|
173
|
+
@voice_conn_retry_2 = Faraday.new(@voice_base_uri_fallback_2) do |faraday|
|
174
|
+
faraday.headers = @headers
|
175
|
+
|
176
|
+
# DANGER: Basic auth should always come after headers, else
|
177
|
+
# The headers will replace the basic_auth
|
178
|
+
|
179
|
+
faraday.basic_auth(auth_id, auth_token)
|
180
|
+
|
181
|
+
faraday.proxy=@proxy_hash if @proxy_hash
|
182
|
+
faraday.response :json, content_type: /\bjson$/
|
183
|
+
faraday.adapter Faraday.default_adapter
|
184
|
+
end
|
185
|
+
|
186
|
+
@callinsights_conn = Faraday.new(@callinsights_base_uri) do |faraday|
|
187
|
+
faraday.headers = @headers
|
188
|
+
|
189
|
+
# DANGER: Basic auth should always come after headers, else
|
190
|
+
# The headers will replace the basic_auth
|
191
|
+
|
192
|
+
faraday.basic_auth(auth_id, auth_token)
|
193
|
+
|
194
|
+
faraday.proxy=@proxy_hash if @proxy_hash
|
195
|
+
faraday.response :json, content_type: /\bjson$/
|
196
|
+
faraday.adapter Faraday.default_adapter
|
197
|
+
end
|
198
|
+
|
199
|
+
@lookup_conn = Faraday.new(@lookup_base_uri) do |faraday|
|
200
|
+
faraday.headers = @headers
|
201
|
+
|
202
|
+
# DANGER: Basic auth should always come after headers, else
|
203
|
+
# The headers will replace the basic_auth
|
204
|
+
|
205
|
+
faraday.basic_auth(auth_id, auth_token)
|
206
|
+
|
207
|
+
faraday.proxy=@proxy_hash if @proxy_hash
|
208
|
+
faraday.response :json, content_type: /\bjson$/
|
209
|
+
faraday.adapter Faraday.default_adapter
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def send_get(resource_path, data, timeout, options = nil)
|
214
|
+
if options
|
215
|
+
if options[:voice_retry_count] == 0 and options[:is_voice_request] == true
|
216
|
+
response = @voice_conn_no_retry.get do |req|
|
217
|
+
req.url resource_path, data
|
218
|
+
req.options.timeout = timeout if timeout
|
219
|
+
end
|
220
|
+
elsif options[:voice_retry_count] == 1 and options[:is_voice_request] == true
|
221
|
+
response = @voice_conn_retry_1.get do |req|
|
222
|
+
req.url resource_path, data
|
223
|
+
req.options.timeout = timeout if timeout
|
224
|
+
end
|
225
|
+
elsif options[:voice_retry_count] == 2 and options[:is_voice_request] == true
|
226
|
+
response = @voice_conn_retry_2.get do |req|
|
227
|
+
req.url resource_path, data
|
228
|
+
req.options.timeout = timeout if timeout
|
229
|
+
end
|
230
|
+
elsif options[:is_lookup_request] == true
|
231
|
+
response = @lookup_conn.get do |req|
|
232
|
+
req.url resource_path, data
|
233
|
+
req.options.timeout = timeout if timeout
|
234
|
+
end
|
235
|
+
end
|
236
|
+
else
|
237
|
+
response = @conn.get do |req|
|
238
|
+
req.url resource_path, data
|
239
|
+
req.options.timeout = timeout if timeout
|
240
|
+
end
|
241
|
+
end
|
242
|
+
response
|
243
|
+
end
|
244
|
+
|
245
|
+
def send_post(resource_path, data, timeout, use_multipart_conn, options = nil)
|
246
|
+
if use_multipart_conn
|
247
|
+
multipart_conn = Faraday.new(@base_uri) do |faraday|
|
248
|
+
faraday.headers = {
|
249
|
+
'User-Agent' => @headers['User-Agent'],
|
250
|
+
'Accept' => @headers['Accept']
|
251
|
+
}
|
252
|
+
|
253
|
+
# DANGER: Basic auth should always come after headers, else
|
254
|
+
# The headers will replace the basic_auth
|
255
|
+
|
256
|
+
faraday.request :multipart
|
257
|
+
faraday.request :url_encoded
|
258
|
+
faraday.basic_auth(auth_id, auth_token)
|
259
|
+
|
260
|
+
faraday.proxy=@proxy_hash if @proxy_hash
|
261
|
+
faraday.response :json, content_type: /\bjson$/
|
262
|
+
faraday.adapter Faraday.default_adapter
|
263
|
+
end
|
264
|
+
|
265
|
+
response = multipart_conn.post do |req|
|
266
|
+
req.url resource_path
|
267
|
+
req.options.timeout = timeout if timeout
|
268
|
+
req.body = data
|
269
|
+
puts req
|
270
|
+
end
|
271
|
+
else
|
272
|
+
if !data.nil? && (data.has_key? 'is_callinsights_request')
|
273
|
+
callinsight_base_url = data['callinsight_base_url']
|
274
|
+
resource_path = data['request_url']
|
275
|
+
data.delete('is_callinsights_request')
|
276
|
+
data.delete('request_url')
|
277
|
+
|
278
|
+
response = @callinsights_conn.post do |req|
|
279
|
+
req.url resource_path
|
280
|
+
req.options.timeout = timeout if timeout
|
281
|
+
req.body = JSON.generate(data) if data
|
282
|
+
end
|
283
|
+
elsif options
|
284
|
+
if options[:voice_retry_count] == 0 and options[:is_voice_request] == true
|
285
|
+
response = @voice_conn_no_retry.post do |req|
|
286
|
+
req.url resource_path
|
287
|
+
req.options.timeout = timeout if timeout
|
288
|
+
req.body = JSON.generate(data) if data
|
289
|
+
end
|
290
|
+
elsif options[:voice_retry_count] == 1 and options[:is_voice_request] == true
|
291
|
+
response = @voice_conn_retry_1.post do |req|
|
292
|
+
req.url resource_path
|
293
|
+
req.options.timeout = timeout if timeout
|
294
|
+
req.body = JSON.generate(data) if data
|
295
|
+
end
|
296
|
+
elsif options[:voice_retry_count] == 2 and options[:is_voice_request] == true
|
297
|
+
response = @voice_conn_retry_2.post do |req|
|
298
|
+
req.url resource_path
|
299
|
+
req.options.timeout = timeout if timeout
|
300
|
+
req.body = JSON.generate(data) if data
|
301
|
+
end
|
302
|
+
end
|
303
|
+
else
|
304
|
+
response = @conn.post do |req|
|
305
|
+
req.url resource_path
|
306
|
+
req.options.timeout = timeout if timeout
|
307
|
+
req.body = JSON.generate(data) if data
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
response
|
312
|
+
end
|
313
|
+
|
314
|
+
def send_delete(resource_path, data, timeout, options = nil)
|
315
|
+
if options
|
316
|
+
if options[:voice_retry_count] == 0 and options[:is_voice_request] == true
|
317
|
+
response = @voice_conn_no_retry.delete do |req|
|
318
|
+
req.url resource_path
|
319
|
+
req.options.timeout = timeout if timeout
|
320
|
+
req.body = JSON.generate(data) if data
|
321
|
+
end
|
322
|
+
elsif options[:voice_retry_count] == 1 and options[:is_voice_request] == true
|
323
|
+
response = @voice_conn_retry_1.delete do |req|
|
324
|
+
req.url resource_path
|
325
|
+
req.options.timeout = timeout if timeout
|
326
|
+
req.body = JSON.generate(data) if data
|
327
|
+
end
|
328
|
+
elsif options[:voice_retry_count] == 2 and options[:is_voice_request] == true
|
329
|
+
response = @voice_conn_retry_2.delete do |req|
|
330
|
+
req.url resource_path
|
331
|
+
req.options.timeout = timeout if timeout
|
332
|
+
req.body = JSON.generate(data) if data
|
333
|
+
end
|
334
|
+
end
|
335
|
+
else
|
336
|
+
response = @conn.delete do |req|
|
337
|
+
req.url resource_path
|
338
|
+
req.options.timeout = timeout if timeout
|
339
|
+
req.body = JSON.generate(data) if data
|
340
|
+
end
|
341
|
+
end
|
342
|
+
response
|
343
|
+
end
|
344
|
+
|
345
|
+
def handle_response_exceptions(response)
|
346
|
+
exception_mapping = {
|
347
|
+
400 => [
|
348
|
+
Exceptions::ValidationError,
|
349
|
+
'A parameter is missing or is invalid while accessing resource'
|
350
|
+
],
|
351
|
+
401 => [
|
352
|
+
Exceptions::AuthenticationError,
|
353
|
+
'Failed to authenticate while accessing resource'
|
354
|
+
],
|
355
|
+
404 => [
|
356
|
+
Exceptions::ResourceNotFoundError,
|
357
|
+
'Resource not found'
|
358
|
+
],
|
359
|
+
405 => [
|
360
|
+
Exceptions::InvalidRequestError,
|
361
|
+
'HTTP method used is not allowed to access resource'
|
362
|
+
],
|
363
|
+
409 => [
|
364
|
+
Exceptions::InvalidRequestError,
|
365
|
+
'Conflict'
|
366
|
+
],
|
367
|
+
422 => [
|
368
|
+
Exceptions::InvalidRequestError,
|
369
|
+
'Unprocessable Entity'
|
370
|
+
],
|
371
|
+
500 => [
|
372
|
+
Exceptions::PlivoServerError,
|
373
|
+
'A server error occurred while accessing resource'
|
374
|
+
]
|
375
|
+
}
|
376
|
+
|
377
|
+
response_json = response[:body]
|
378
|
+
return unless exception_mapping.key? response[:status]
|
379
|
+
|
380
|
+
exception_now = exception_mapping[response[:status]]
|
381
|
+
error_message = if (response_json.is_a? Hash) && (response_json.key? 'error')
|
382
|
+
response_json['error']
|
383
|
+
else
|
384
|
+
exception_now[1] + " at: #{response[:url]}"
|
385
|
+
end
|
386
|
+
if error_message.is_a?(Hash) && error_message.key?('error')
|
387
|
+
error_message = error_message['error']
|
388
|
+
end
|
389
|
+
|
390
|
+
raise exception_now[0], error_message.to_s
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Plivo
|
2
|
+
##
|
3
|
+
# The exceptions module that helps in passing on errors to the user in a better way.
|
4
|
+
module Exceptions
|
5
|
+
##
|
6
|
+
# This is Plivo's base error and will be raised when there is an unknown
|
7
|
+
# error that is not covered by other errors.
|
8
|
+
PlivoRESTError = Class.new(StandardError)
|
9
|
+
|
10
|
+
##
|
11
|
+
# This will be raised when A parameter is missing or is invalid while
|
12
|
+
# accessing resource.
|
13
|
+
ValidationError = Class.new(PlivoRESTError)
|
14
|
+
# 'A parameter is missing or is invalid while accessing resource'
|
15
|
+
|
16
|
+
##
|
17
|
+
# This will be raised when there is an an error authenticating the request.
|
18
|
+
#
|
19
|
+
# It is because there were no authentication credentials found or passed
|
20
|
+
# or the auth credentials that were found or passed were incorrect.
|
21
|
+
AuthenticationError = Class.new(PlivoRESTError)
|
22
|
+
|
23
|
+
##
|
24
|
+
# This will be raised when one or more parameters passed to Plivo servers
|
25
|
+
# is invalid.
|
26
|
+
#
|
27
|
+
# More specific error message will be displayed wherever possible.
|
28
|
+
InvalidRequestError = Class.new(PlivoRESTError)
|
29
|
+
|
30
|
+
##
|
31
|
+
# This will be raised when there is a server error on the Plivo end.
|
32
|
+
#
|
33
|
+
# This is rarely encountered. You might want to catch this error and
|
34
|
+
# retry the request if needed.
|
35
|
+
#
|
36
|
+
# If retrying doesn't help, please contact https://support.plivo.com
|
37
|
+
# immediately.
|
38
|
+
PlivoServerError = Class.new(PlivoRESTError)
|
39
|
+
|
40
|
+
##
|
41
|
+
# This will be raised when there is an XML generation error.
|
42
|
+
#
|
43
|
+
# Usually, the reason why this error is raised will be included.
|
44
|
+
PlivoXMLError = Class.new(PlivoRESTError)
|
45
|
+
|
46
|
+
##
|
47
|
+
# This will be raised when there is an authentication error
|
48
|
+
ResourceNotFoundError = Class.new(PlivoRESTError)
|
49
|
+
end
|
50
|
+
end
|