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