simplyq 0.8.0rc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +58 -0
- data/.rubocop_todo.yml +156 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +27 -0
- data/LICENSE.txt +21 -0
- data/README.md +37 -0
- data/Rakefile +12 -0
- data/lib/simplyq/api/application_api.rb +82 -0
- data/lib/simplyq/api/endpoint_api.rb +178 -0
- data/lib/simplyq/api/event_api.rb +140 -0
- data/lib/simplyq/client.rb +304 -0
- data/lib/simplyq/configuration.rb +185 -0
- data/lib/simplyq/errors.rb +96 -0
- data/lib/simplyq/models/application.rb +196 -0
- data/lib/simplyq/models/delivery_attempt.rb +110 -0
- data/lib/simplyq/models/endpoint.rb +226 -0
- data/lib/simplyq/models/event.rb +133 -0
- data/lib/simplyq/models/inbound_event.rb +37 -0
- data/lib/simplyq/models/list.rb +120 -0
- data/lib/simplyq/version.rb +5 -0
- data/lib/simplyq/webhook.rb +102 -0
- data/lib/simplyq.rb +26 -0
- data/sig/simplyq.rbs +4 -0
- data/simplyq.gemspec +40 -0
- metadata +121 -0
@@ -0,0 +1,140 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
require "time"
|
5
|
+
|
6
|
+
module Simplyq
|
7
|
+
module API
|
8
|
+
class EventAPI
|
9
|
+
attr_reader :client
|
10
|
+
|
11
|
+
API_PATH = "/v1/application/{app_id}/event"
|
12
|
+
API_RETRIEVE_PATH = "/v1/application/{app_id}/event/{event_id}"
|
13
|
+
API_DELIVERY_ATTEMPTS_PATH = "/v1/application/{app_id}/event/{event_id}/delivery_attempt"
|
14
|
+
API_DELIVERY_ATTEMPT_PATH = "/v1/application/{app_id}/event/{event_id}/delivery_attempt/{delivery_attempt_id}/"
|
15
|
+
API_ENDPOINTS_PATH = "/v1/application/{app_id}/event/{event_id}/endpoint"
|
16
|
+
API_RETRY_PATH = "/v1/application/{app_id}/endpoint/{endpoint_id}/event/{event_id}"
|
17
|
+
|
18
|
+
# Initializes a new API object.
|
19
|
+
#
|
20
|
+
# @param client [Simplyq::Client] the client object that will be used to
|
21
|
+
# make HTTP requests.
|
22
|
+
def initialize(client)
|
23
|
+
@client = client
|
24
|
+
end
|
25
|
+
|
26
|
+
def retrieve(application_id, event_id)
|
27
|
+
path = API_RETRIEVE_PATH.gsub("{app_id}", application_id.to_s).gsub("{event_id}", event_id.to_s)
|
28
|
+
|
29
|
+
data, status, headers = client.call_api(:get, path)
|
30
|
+
decerialize(data)
|
31
|
+
end
|
32
|
+
|
33
|
+
def list(application_id, params = {})
|
34
|
+
path = API_PATH.gsub("{app_id}", application_id.to_s)
|
35
|
+
|
36
|
+
data, status, headers = client.call_api(:get, path, { query_params: params })
|
37
|
+
decerialize_list(data, params: params, list_args: [application_id])
|
38
|
+
end
|
39
|
+
|
40
|
+
def create(application_id, event)
|
41
|
+
path = API_PATH.gsub("{app_id}", application_id.to_s)
|
42
|
+
|
43
|
+
data, status, headers = client.call_api(:post, path, { body: build_model(event).to_h })
|
44
|
+
decerialize(data)
|
45
|
+
end
|
46
|
+
|
47
|
+
def retrieve_delivery_attempts(application_id, event_id, params = {})
|
48
|
+
path = API_DELIVERY_ATTEMPTS_PATH.gsub("{app_id}", application_id.to_s).gsub("{event_id}", event_id.to_s)
|
49
|
+
|
50
|
+
data, status, headers = client.call_api(:get, path, { query_params: params })
|
51
|
+
decerialize_delivery_attempts_list(data, params: params, list_args: [application_id, event_id])
|
52
|
+
end
|
53
|
+
|
54
|
+
def retrieve_endpoints(application_id, event_id, params = {})
|
55
|
+
path = API_ENDPOINTS_PATH.gsub("{app_id}", application_id.to_s).gsub("{event_id}", event_id.to_s)
|
56
|
+
|
57
|
+
data, status, headers = client.call_api(:get, path, { query_params: params })
|
58
|
+
decerialize_endpoints_list(data, params: params, list_args: [application_id, event_id])
|
59
|
+
end
|
60
|
+
|
61
|
+
def retry(application_id, endpoint_id, event_id)
|
62
|
+
path = API_RETRY_PATH.gsub("{app_id}", application_id.to_s)
|
63
|
+
.gsub("{endpoint_id}", endpoint_id.to_s)
|
64
|
+
.gsub("{event_id}", event_id.to_s)
|
65
|
+
|
66
|
+
data, status, headers = client.call_api(:post, path)
|
67
|
+
status == 202
|
68
|
+
end
|
69
|
+
|
70
|
+
def retrieve_delivery_attempt(application_id, event_id, delivery_attempt_id)
|
71
|
+
path = API_DELIVERY_ATTEMPT_PATH.gsub("{app_id}", application_id.to_s)
|
72
|
+
.gsub("{event_id}", event_id.to_s)
|
73
|
+
.gsub("{delivery_attempt_id}", delivery_attempt_id.to_s)
|
74
|
+
|
75
|
+
data, status, headers = client.call_api(:get, path)
|
76
|
+
decerialize_delivery_attempt(data)
|
77
|
+
end
|
78
|
+
|
79
|
+
private def build_model(data)
|
80
|
+
return data if data.is_a?(Simplyq::Model::Event)
|
81
|
+
raise ArgumentError, "Invalid data must be a Simplyq::Model::Event or Hash" unless data.is_a?(Hash)
|
82
|
+
|
83
|
+
Simplyq::Model::Event.from_hash(data)
|
84
|
+
end
|
85
|
+
|
86
|
+
private def decerialize(json_data)
|
87
|
+
data = body_to_json(json_data)
|
88
|
+
|
89
|
+
Simplyq::Model::Event.from_hash(data)
|
90
|
+
end
|
91
|
+
|
92
|
+
private def decerialize_delivery_attempt(json_data)
|
93
|
+
data = body_to_json(json_data)
|
94
|
+
|
95
|
+
Simplyq::Model::DeliveryAttempt.from_hash(data)
|
96
|
+
end
|
97
|
+
|
98
|
+
private def decerialize_list(json_data, params: {}, list_args: [])
|
99
|
+
data = body_to_json(json_data)
|
100
|
+
|
101
|
+
Simplyq::Model::List.new(
|
102
|
+
Simplyq::Model::Event, data,
|
103
|
+
api_method: :list,
|
104
|
+
list_args: list_args,
|
105
|
+
filters: params, api: self
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
private def decerialize_delivery_attempts_list(json_data, params: {}, list_args: [])
|
110
|
+
data = body_to_json(json_data)
|
111
|
+
|
112
|
+
Simplyq::Model::List.new(
|
113
|
+
Simplyq::Model::DeliveryAttempt, data,
|
114
|
+
api_method: :retrieve_delivery_attempts,
|
115
|
+
list_args: list_args,
|
116
|
+
filters: params, api: self
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
private def decerialize_endpoints_list(json_data, params: {}, list_args: [])
|
121
|
+
data = body_to_json(json_data)
|
122
|
+
|
123
|
+
Simplyq::Model::List.new(
|
124
|
+
Simplyq::Model::Endpoint, data,
|
125
|
+
api_method: :retrieve_endpoints,
|
126
|
+
list_args: list_args,
|
127
|
+
filters: params, api: self
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
private def body_to_json(body)
|
132
|
+
return if body.nil?
|
133
|
+
|
134
|
+
JSON.parse(body, symbolize_names: true)
|
135
|
+
rescue JSON::ParserError
|
136
|
+
raise Simplyq::APIError.new("Invalid JSON in response body.", http_body: body)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,304 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "faraday"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
module Simplyq
|
7
|
+
class Client
|
8
|
+
HEADER_AUTHORIZATION = "Authorization"
|
9
|
+
|
10
|
+
USER_AGENT = "simplyq-ruby/#{Simplyq::VERSION}"
|
11
|
+
|
12
|
+
attr_reader :config
|
13
|
+
|
14
|
+
# Initialize client to connect to SimplyQ API
|
15
|
+
#
|
16
|
+
# @param config_options [Simplyq::Configuration|Hash] a configuration object or a hash of configuration options
|
17
|
+
def initialize(config_options = {})
|
18
|
+
@config = case config_options
|
19
|
+
when Hash
|
20
|
+
Simplyq::Configuration.setup do |config|
|
21
|
+
config_options.each do |key, value|
|
22
|
+
config.send("#{key}=", value)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
when Simplyq::Configuration
|
26
|
+
config_options
|
27
|
+
else
|
28
|
+
raise ArgumentError, "Invalid configuration options #{config_options}"
|
29
|
+
end
|
30
|
+
@default_headers = {
|
31
|
+
"Content-Type" => "application/json",
|
32
|
+
"User-Agent" => USER_AGENT
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def applications
|
37
|
+
@applications ||= Simplyq::API::ApplicationAPI.new(self)
|
38
|
+
end
|
39
|
+
|
40
|
+
def endpoints
|
41
|
+
@endpoints ||= Simplyq::API::EndpointAPI.new(self)
|
42
|
+
end
|
43
|
+
|
44
|
+
def events
|
45
|
+
@events ||= Simplyq::API::EventAPI.new(self)
|
46
|
+
end
|
47
|
+
|
48
|
+
def check_api_key!
|
49
|
+
raise AuthenticationError, "No API key provided." unless config.api_key
|
50
|
+
|
51
|
+
raise AuthenticationError, "Invalid API key as it includes spaces" if config.api_key =~ /\s/
|
52
|
+
end
|
53
|
+
|
54
|
+
ERROR_MESSAGE_CONNECTION =
|
55
|
+
"Unexpected error communicating when trying to connect to " \
|
56
|
+
"SimplyQ (%s). You may be seeing this message because your DNS is not " \
|
57
|
+
"working or you don't have an internet connection. To check, try " \
|
58
|
+
"running `host api.simplyq.com` from the command line."
|
59
|
+
ERROR_MESSAGE_SSL =
|
60
|
+
"Could not establish a secure connection to SimplyQ (%s), you " \
|
61
|
+
"may need to upgrade your OpenSSL version. To check, try running " \
|
62
|
+
"`openssl s_client -connect api.simplyq.com:443` from the command " \
|
63
|
+
"line."
|
64
|
+
|
65
|
+
ERROR_MESSAGE_TIMEOUT_SUFFIX =
|
66
|
+
"Please check your internet connection and try again. " \
|
67
|
+
"If this problem persists, you should check SimplyQ's service " \
|
68
|
+
"status at https://simplyq.statuspage.io, or let us know at " \
|
69
|
+
"support@simplyq.io."
|
70
|
+
|
71
|
+
ERROR_MESSAGE_TIMEOUT_CONNECT =
|
72
|
+
"Timed out connecting to SimplyQ (%s). #{ERROR_MESSAGE_TIMEOUT_SUFFIX}"
|
73
|
+
|
74
|
+
ERROR_MESSAGE_TIMEOUT_READ =
|
75
|
+
"Timed out communicating with SimplyQ (%s). #{ERROR_MESSAGE_TIMEOUT_SUFFIX}"
|
76
|
+
|
77
|
+
NETWORK_ERROR_MESSAGES_MAP = {
|
78
|
+
EOFError => ERROR_MESSAGE_CONNECTION,
|
79
|
+
Errno::ECONNREFUSED => ERROR_MESSAGE_CONNECTION,
|
80
|
+
Errno::ECONNRESET => ERROR_MESSAGE_CONNECTION,
|
81
|
+
Errno::EHOSTUNREACH => ERROR_MESSAGE_CONNECTION,
|
82
|
+
Errno::ETIMEDOUT => ERROR_MESSAGE_TIMEOUT_CONNECT,
|
83
|
+
SocketError => ERROR_MESSAGE_CONNECTION,
|
84
|
+
|
85
|
+
Net::OpenTimeout => ERROR_MESSAGE_TIMEOUT_CONNECT,
|
86
|
+
Net::ReadTimeout => ERROR_MESSAGE_TIMEOUT_READ,
|
87
|
+
|
88
|
+
Faraday::TimeoutError => ERROR_MESSAGE_TIMEOUT_READ,
|
89
|
+
Faraday::ConnectionFailed => ERROR_MESSAGE_CONNECTION,
|
90
|
+
|
91
|
+
OpenSSL::SSL::SSLError => ERROR_MESSAGE_SSL,
|
92
|
+
Faraday::SSLError => ERROR_MESSAGE_SSL
|
93
|
+
}.freeze
|
94
|
+
private_constant :NETWORK_ERROR_MESSAGES_MAP
|
95
|
+
|
96
|
+
# Call an API with given options.
|
97
|
+
#
|
98
|
+
# @return [Array<(Object, Integer, Hash)>] an array of 3 elements:
|
99
|
+
# the data deserialized from response body (could be nil), response status code and response headers.
|
100
|
+
def call_api(http_method, path, opts = {})
|
101
|
+
check_api_key!
|
102
|
+
|
103
|
+
begin
|
104
|
+
response = connection.public_send(http_method.to_sym.downcase) do |req|
|
105
|
+
build_request(http_method, path, req, opts)
|
106
|
+
end
|
107
|
+
|
108
|
+
config.logger.debug "HTTP response body ~BEGIN~\n#{response.body}\n~END~\n" if config.debugging
|
109
|
+
|
110
|
+
unless response.success?
|
111
|
+
if response.status.zero?
|
112
|
+
# Errors from libcurl will be made visible here
|
113
|
+
raise ApiError.new(response.reason_phrase, http_status: 0)
|
114
|
+
else
|
115
|
+
raise specific_http_error(response, get_http_error_data(response).merge(params: opts[:query_params]))
|
116
|
+
end
|
117
|
+
end
|
118
|
+
rescue *NETWORK_ERROR_MESSAGES_MAP.keys => e
|
119
|
+
handle_network_error(e)
|
120
|
+
end
|
121
|
+
|
122
|
+
[response.body, response.status, response.headers]
|
123
|
+
end
|
124
|
+
|
125
|
+
def handle_network_error(error)
|
126
|
+
errors, message = NETWORK_ERROR_MESSAGES_MAP.detect do |(e, _)|
|
127
|
+
error.is_a?(e)
|
128
|
+
end
|
129
|
+
|
130
|
+
if errors.nil?
|
131
|
+
message = "Unexpected error #{error.class.name} communicating " \
|
132
|
+
"with SimplyQ. Please let us know at support@simplyq.io."
|
133
|
+
end
|
134
|
+
|
135
|
+
message = message % config.base_url
|
136
|
+
message += "\n\n(Network error: #{error.message})"
|
137
|
+
|
138
|
+
raise APIConnectionError.new(message, http_status: 0, error: error)
|
139
|
+
end
|
140
|
+
|
141
|
+
def get_http_error_data(response)
|
142
|
+
body = safe_json_parse_body(response)
|
143
|
+
if body.is_a?(Hash)
|
144
|
+
message = body[:error] || body[:message]
|
145
|
+
|
146
|
+
message = "Invalid request" if message.nil? && body[:errors]
|
147
|
+
|
148
|
+
return {
|
149
|
+
message: message,
|
150
|
+
errors: body[:errors],
|
151
|
+
code: body[:code]
|
152
|
+
}
|
153
|
+
end
|
154
|
+
|
155
|
+
{ message: response.reason_phrase }
|
156
|
+
end
|
157
|
+
|
158
|
+
def safe_json_parse_body(response)
|
159
|
+
return nil if response.body.nil?
|
160
|
+
|
161
|
+
JSON.parse(response.body, symbolize_names: true)
|
162
|
+
rescue JSON::ParserError
|
163
|
+
nil
|
164
|
+
end
|
165
|
+
|
166
|
+
def specific_http_error(resp, error_data = {})
|
167
|
+
# The standard arguments that are passed to API exceptions
|
168
|
+
opts = {
|
169
|
+
http_body: resp.body,
|
170
|
+
http_headers: resp.headers,
|
171
|
+
http_status: resp.status,
|
172
|
+
code: error_data[:code]
|
173
|
+
}
|
174
|
+
|
175
|
+
case resp.status
|
176
|
+
when 400, 404, 422
|
177
|
+
case error_data[:type]
|
178
|
+
when "idempotency_error"
|
179
|
+
IdempotencyError.new(error_data[:message], **opts)
|
180
|
+
else
|
181
|
+
InvalidRequestError.new(
|
182
|
+
error_data[:message], error_data[:param],
|
183
|
+
**opts.merge(errors: error_data[:errors])
|
184
|
+
)
|
185
|
+
end
|
186
|
+
when 401
|
187
|
+
AuthenticationError.new(error_data[:message] || resp.reason_phrase, **opts)
|
188
|
+
when 402
|
189
|
+
PaymentRequiredError.new(error_data[:message] || resp.reason_phrase, **opts)
|
190
|
+
when 403
|
191
|
+
PermissionError.new(error_data[:message] || resp.reason_phrase, **opts)
|
192
|
+
when 429
|
193
|
+
RateLimitError.new(error_data[:message] || resp.reason_phrase, **opts)
|
194
|
+
else
|
195
|
+
APIError.new(error_data[:message] || resp.reason_phrase, **opts)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def build_request_url(path)
|
200
|
+
# Add leading and trailing slashes to path
|
201
|
+
path = "/#{path}".gsub(%r{/+}, "/")
|
202
|
+
@config.base_url + path
|
203
|
+
end
|
204
|
+
|
205
|
+
# Builds the HTTP request
|
206
|
+
#
|
207
|
+
# @param [String] http_method HTTP method/verb (e.g. POST)
|
208
|
+
# @param [String] path URL path (e.g. /account/new)
|
209
|
+
# @option opts [Hash] :header_params Header parameters
|
210
|
+
# @option opts [Hash] :query_params Query parameters
|
211
|
+
# @option opts [Hash] :form_params Query parameters
|
212
|
+
# @option opts [Object] :body HTTP body (JSON/XML)
|
213
|
+
# @return [Faraday::Request] A Faraday Request
|
214
|
+
def build_request(http_method, path, request, opts = {})
|
215
|
+
url = build_request_url(path)
|
216
|
+
http_method = http_method.to_sym.downcase
|
217
|
+
|
218
|
+
header_params = @default_headers.merge(opts[:header_params] || {})
|
219
|
+
query_params = opts[:query_params] || {}
|
220
|
+
form_params = opts[:form_params] || {}
|
221
|
+
|
222
|
+
header_params[HEADER_AUTHORIZATION] = config.auth_api_key
|
223
|
+
|
224
|
+
if %i[post patch put delete].include?(http_method)
|
225
|
+
req_body = build_request_body(header_params, form_params, opts[:body])
|
226
|
+
config.logger.debug "HTTP request body param ~BEGIN~\n#{req_body}\n~END~\n" if config.debugging
|
227
|
+
end
|
228
|
+
request.headers = header_params
|
229
|
+
request.body = req_body
|
230
|
+
|
231
|
+
# Overload default options only if provided
|
232
|
+
request.options.timeout = config.timeout if config.timeout
|
233
|
+
|
234
|
+
request.url url
|
235
|
+
request.params = query_params
|
236
|
+
download_file(request) if opts[:return_type] == "File" || opts[:return_type] == "Binary"
|
237
|
+
request
|
238
|
+
end
|
239
|
+
|
240
|
+
# Builds the HTTP request body
|
241
|
+
#
|
242
|
+
# @param [Hash] header_params Header parameters
|
243
|
+
# @param [Hash] form_params Query parameters
|
244
|
+
# @param [Object] body HTTP body (JSON/XML)
|
245
|
+
# @return [String] HTTP body data in the form of string
|
246
|
+
def build_request_body(header_params, form_params, body)
|
247
|
+
# http form
|
248
|
+
if header_params["Content-Type"] == "application/x-www-form-urlencoded"
|
249
|
+
data = URI.encode_www_form(form_params)
|
250
|
+
elsif header_params["Content-Type"] == "multipart/form-data"
|
251
|
+
data = {}
|
252
|
+
form_params.each do |key, value|
|
253
|
+
data[key] = case value
|
254
|
+
when ::File, ::Tempfile
|
255
|
+
Faraday::FilePart.new(value.path, "application/octet-stream", value.path)
|
256
|
+
when ::Array, nil
|
257
|
+
# let Faraday handle Array and nil parameters
|
258
|
+
value
|
259
|
+
else
|
260
|
+
value.to_s
|
261
|
+
end
|
262
|
+
end
|
263
|
+
elsif body
|
264
|
+
data = body.is_a?(String) ? body : body.to_json
|
265
|
+
else
|
266
|
+
data = nil
|
267
|
+
end
|
268
|
+
data
|
269
|
+
end
|
270
|
+
|
271
|
+
def connection
|
272
|
+
@connection ||= build_connection
|
273
|
+
end
|
274
|
+
|
275
|
+
def build_connection
|
276
|
+
Faraday.new(url: config.base_url, ssl: ssl_options, proxy: config.proxy) do |conn|
|
277
|
+
basic_auth(conn)
|
278
|
+
config.configure_middleware(conn)
|
279
|
+
yield(conn) if block_given?
|
280
|
+
conn.adapter(Faraday.default_adapter)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def ssl_options
|
285
|
+
{
|
286
|
+
ca_file: config.ssl_ca_file,
|
287
|
+
verify: config.ssl_verify,
|
288
|
+
verify_mode: config.ssl_verify_mode,
|
289
|
+
client_cert: config.ssl_client_cert,
|
290
|
+
client_key: config.ssl_client_key
|
291
|
+
}
|
292
|
+
end
|
293
|
+
|
294
|
+
def basic_auth(conn)
|
295
|
+
if config.username && config.password
|
296
|
+
if Gem::Version.new(Faraday::VERSION) >= Gem::Version.new("2.0")
|
297
|
+
conn.request(:authorization, :basic, config.username, config.password)
|
298
|
+
else
|
299
|
+
conn.request(:basic_auth, config.username, config.password)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
|
5
|
+
module Simplyq
|
6
|
+
class Configuration
|
7
|
+
# Defines API keys used with API Key authentications.
|
8
|
+
attr_accessor :api_key
|
9
|
+
|
10
|
+
# Defines the api version
|
11
|
+
attr_accessor :api_version
|
12
|
+
|
13
|
+
# Defines the logger used for debugging.
|
14
|
+
# Default to `Rails.logger` (when in Rails) or logging to STDOUT.
|
15
|
+
#
|
16
|
+
# @return [#debug]
|
17
|
+
attr_accessor :logger
|
18
|
+
|
19
|
+
# Defines the username used with HTTP basic authentication.
|
20
|
+
#
|
21
|
+
# @return [String]
|
22
|
+
attr_accessor :username
|
23
|
+
|
24
|
+
# Defines the password used with HTTP basic authentication.
|
25
|
+
#
|
26
|
+
# @return [String]
|
27
|
+
attr_accessor :password
|
28
|
+
|
29
|
+
# Set this to false to skip client side validation in the operation.
|
30
|
+
# Default to true.
|
31
|
+
# @return [true, false]
|
32
|
+
attr_accessor :client_side_validation
|
33
|
+
|
34
|
+
### TLS/SSL setting
|
35
|
+
# Set this to false to skip verifying SSL certificate when calling API from https server.
|
36
|
+
# Default to true.
|
37
|
+
#
|
38
|
+
# @note Do NOT set it to false in production code, otherwise you would face multiple types of cryptographic attacks.
|
39
|
+
#
|
40
|
+
# @return [true, false]
|
41
|
+
attr_accessor :ssl_verify
|
42
|
+
|
43
|
+
### TLS/SSL setting
|
44
|
+
# Any `OpenSSL::SSL::` constant (see https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/SSL.html)
|
45
|
+
#
|
46
|
+
# @note Do NOT set it to false in production code, otherwise you would face multiple types of cryptographic attacks.
|
47
|
+
#
|
48
|
+
attr_accessor :ssl_verify_mode
|
49
|
+
|
50
|
+
### TLS/SSL setting
|
51
|
+
# Set this to customize the certificate file to verify the peer.
|
52
|
+
#
|
53
|
+
# @return [String] the path to the certificate file
|
54
|
+
attr_accessor :ssl_ca_file
|
55
|
+
|
56
|
+
### TLS/SSL setting
|
57
|
+
# Client certificate file (for client certificate)
|
58
|
+
attr_accessor :ssl_client_cert
|
59
|
+
|
60
|
+
### TLS/SSL setting
|
61
|
+
# Client private key file (for client certificate)
|
62
|
+
attr_accessor :ssl_client_key
|
63
|
+
|
64
|
+
### Proxy setting
|
65
|
+
# HTTP Proxy settings
|
66
|
+
attr_accessor :proxy
|
67
|
+
|
68
|
+
attr_accessor :timeout
|
69
|
+
|
70
|
+
attr_accessor :base_url
|
71
|
+
|
72
|
+
attr_accessor :debugging
|
73
|
+
|
74
|
+
attr_reader :open_timeout
|
75
|
+
attr_reader :read_timeout
|
76
|
+
attr_reader :write_timeout
|
77
|
+
|
78
|
+
def self.setup
|
79
|
+
new.tap do |instance|
|
80
|
+
yield(instance) if block_given?
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def initialize
|
85
|
+
@timeout = 30
|
86
|
+
@open_timeout = 30
|
87
|
+
@read_timeout = 80
|
88
|
+
@write_timeout = 30
|
89
|
+
|
90
|
+
@client_side_validation = true
|
91
|
+
|
92
|
+
@base_url = "https://api.simplyq.io"
|
93
|
+
@middlewares = Hash.new { |h, k| h[k] = [] }
|
94
|
+
@logger = defined?(Rails) ? Rails.logger : Logger.new($stdout)
|
95
|
+
|
96
|
+
yield(self) if block_given?
|
97
|
+
end
|
98
|
+
|
99
|
+
# The default Configuration object.
|
100
|
+
def self.default
|
101
|
+
Configuration.new
|
102
|
+
end
|
103
|
+
|
104
|
+
# Gets Basic Auth token string
|
105
|
+
def basic_auth_token
|
106
|
+
"Basic #{["#{username}:#{password}"].pack("m").delete("\r\n")}"
|
107
|
+
end
|
108
|
+
|
109
|
+
def auth_api_key
|
110
|
+
"Bearer #{@api_key}"
|
111
|
+
end
|
112
|
+
|
113
|
+
# TODO: Remove
|
114
|
+
# def base_path=(base_path)
|
115
|
+
# # Add leading and trailing slashes to base_path
|
116
|
+
# @base_path = "/#{base_path}".gsub(%r{/+}, "/")
|
117
|
+
# @base_path = "" if @base_path == "/"
|
118
|
+
# end
|
119
|
+
|
120
|
+
# TODO: Remove
|
121
|
+
# Returns base URL for specified operation based on server settings
|
122
|
+
# def base_url(operation = nil)
|
123
|
+
# index = server_operation_index.fetch(operation, server_index)
|
124
|
+
# return "#{scheme}://#{[host, base_path].join("/").gsub(%r{/+}, "/")}".sub(%r{/+\z}, "") if index.nil?
|
125
|
+
|
126
|
+
# server_url(index, server_operation_variables.fetch(operation, server_variables),
|
127
|
+
# operation_server_settings[operation])
|
128
|
+
# end
|
129
|
+
|
130
|
+
# Adds middleware to the stack
|
131
|
+
def use(*middleware)
|
132
|
+
set_faraday_middleware(:use, *middleware)
|
133
|
+
end
|
134
|
+
|
135
|
+
# Adds request middleware to the stack
|
136
|
+
def request(*middleware)
|
137
|
+
set_faraday_middleware(:request, *middleware)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Adds response middleware to the stack
|
141
|
+
def response(*middleware)
|
142
|
+
set_faraday_middleware(:response, *middleware)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Adds Faraday middleware setting information to the stack
|
146
|
+
#
|
147
|
+
# @example Use the `set_faraday_middleware` method to set middleware information
|
148
|
+
# config.set_faraday_middleware(:request, :retry, max: 3, methods: [:get, :post], retry_statuses: [503])
|
149
|
+
# config.set_faraday_middleware(:response, :logger, nil, { bodies: true, log_level: :debug })
|
150
|
+
# config.set_faraday_middleware(:use, Faraday::HttpCache, store: Rails.cache, shared_cache: false)
|
151
|
+
# config.set_faraday_middleware(:insert, 0, FaradayMiddleware::FollowRedirects, { standards_compliant: true, limit: 1 })
|
152
|
+
# config.set_faraday_middleware(:swap, 0, Faraday::Response::Logger)
|
153
|
+
# config.set_faraday_middleware(:delete, Faraday::Multipart::Middleware)
|
154
|
+
#
|
155
|
+
# @see https://github.com/lostisland/faraday/blob/v2.3.0/lib/faraday/rack_builder.rb#L92-L143
|
156
|
+
def set_faraday_middleware(operation, key, *args, &block)
|
157
|
+
unless %i[request response use insert insert_before insert_after swap delete].include?(operation)
|
158
|
+
raise ArgumentError, "Invalid faraday middleware operation #{operation}. Must be" \
|
159
|
+
" :request, :response, :use, :insert, :insert_before, :insert_after, :swap or :delete."
|
160
|
+
end
|
161
|
+
|
162
|
+
@middlewares[operation] << [key, args, block]
|
163
|
+
end
|
164
|
+
ruby2_keywords(:set_faraday_middleware) if respond_to?(:ruby2_keywords, true)
|
165
|
+
|
166
|
+
# Set up middleware on the connection
|
167
|
+
def configure_middleware(connection)
|
168
|
+
return if @middlewares.empty?
|
169
|
+
|
170
|
+
%i[request response use insert insert_before insert_after swap].each do |operation|
|
171
|
+
next unless @middlewares.key?(operation)
|
172
|
+
|
173
|
+
@middlewares[operation].each do |key, args, block|
|
174
|
+
connection.builder.send(operation, key, *args, &block)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
if @middlewares.key?(:delete)
|
179
|
+
@middlewares[:delete].each do |key, _args, _block|
|
180
|
+
connection.builder.delete(key)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|