workato-connector-sdk 1.0.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +1 -0
- data/lib/workato/cli/exec_command.rb +31 -8
- data/lib/workato/cli/multi_auth_selected_fallback.rb +33 -0
- data/lib/workato/cli/oauth2_command.rb +50 -12
- data/lib/workato/connector/sdk/connection.rb +84 -14
- data/lib/workato/connector/sdk/connector.rb +6 -4
- data/lib/workato/connector/sdk/dsl/aws.rb +5 -2
- data/lib/workato/connector/sdk/dsl/call.rb +5 -2
- data/lib/workato/connector/sdk/dsl/csv.rb +125 -0
- data/lib/workato/connector/sdk/dsl/execution_context.rb +44 -0
- data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +8 -1
- data/lib/workato/connector/sdk/dsl.rb +1 -0
- data/lib/workato/connector/sdk/errors.rb +69 -1
- data/lib/workato/connector/sdk/lookup_tables.rb +3 -1
- data/lib/workato/connector/sdk/object_definitions.rb +16 -10
- data/lib/workato/connector/sdk/operation.rb +24 -8
- data/lib/workato/connector/sdk/request.rb +136 -58
- data/lib/workato/connector/sdk/schema.rb +5 -3
- data/lib/workato/connector/sdk/settings.rb +4 -2
- data/lib/workato/connector/sdk/trigger.rb +42 -19
- data/lib/workato/connector/sdk/version.rb +1 -1
- data/lib/workato/connector/sdk.rb +3 -2
- data/lib/workato/extension/case_sensitive_headers.rb +0 -25
- data/lib/workato/extension/content_encoding_decoder.rb +67 -0
- data/lib/workato/extension/currency.rb +1 -1
- data/lib/workato/extension/extra_chain_cert.rb +0 -14
- data/lib/workato/extension/hash_with_indifferent_access.rb +19 -0
- data/lib/workato/extension/phone.rb +1 -1
- data/lib/workato/extension/string.rb +6 -2
- data/lib/workato/utilities/encoding.rb +57 -0
- data/lib/workato/{connector/sdk → utilities}/xml.rb +4 -4
- metadata +48 -22
@@ -0,0 +1,44 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'securerandom'
|
5
|
+
|
6
|
+
module Workato
|
7
|
+
module Connector
|
8
|
+
module Sdk
|
9
|
+
module Dsl
|
10
|
+
module ExecutionContext
|
11
|
+
extend T::Sig
|
12
|
+
extend T::Helpers
|
13
|
+
extend ActiveSupport::Concern
|
14
|
+
|
15
|
+
included do
|
16
|
+
T.bind(self, Class)
|
17
|
+
|
18
|
+
# encrypted safe recipe_id
|
19
|
+
class_attribute :recipe_id, instance_predicate: false, default: SecureRandom.hex(32)
|
20
|
+
end
|
21
|
+
|
22
|
+
sig { returns(T::Hash[Symbol, T.untyped]) }
|
23
|
+
def execution_context
|
24
|
+
@execution_context ||= {
|
25
|
+
recipe_id: recipe_id
|
26
|
+
}.compact
|
27
|
+
end
|
28
|
+
|
29
|
+
# mock unencrypted recipe_id for testing only
|
30
|
+
def recipe_id!
|
31
|
+
recipe_id.reverse
|
32
|
+
end
|
33
|
+
|
34
|
+
module ClassMethods
|
35
|
+
# mock unencrypted recipe_id for testing only
|
36
|
+
def recipe_id!
|
37
|
+
T.unsafe(self).recipe_id.reverse
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -2,6 +2,9 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'jwt'
|
5
|
+
require_relative './csv'
|
6
|
+
|
7
|
+
using Workato::Extension::HashWithIndifferentAccess
|
5
8
|
|
6
9
|
module Workato
|
7
10
|
module Connector
|
@@ -74,7 +77,7 @@ module Workato
|
|
74
77
|
raise "A RSA key of size #{JWT_RSA_KEY_MIN_LENGTH} bits or larger MUST be used with JWT."
|
75
78
|
end
|
76
79
|
|
77
|
-
header_fields =
|
80
|
+
header_fields = HashWithIndifferentAccess.wrap(header_fields).except(:typ, :alg)
|
78
81
|
::JWT.encode(payload, rsa_private, algorithm, header_fields)
|
79
82
|
end
|
80
83
|
|
@@ -152,6 +155,10 @@ module Workato
|
|
152
155
|
def pbkdf2_hmac_sha1(string, salt, iterations = 1000, key_len = 16)
|
153
156
|
Extension::Binary.new(::OpenSSL::PKCS5.pbkdf2_hmac_sha1(string, salt, iterations, key_len))
|
154
157
|
end
|
158
|
+
|
159
|
+
def csv
|
160
|
+
Csv
|
161
|
+
end
|
155
162
|
end
|
156
163
|
end
|
157
164
|
end
|
@@ -6,12 +6,62 @@ module Workato
|
|
6
6
|
module Sdk
|
7
7
|
InvalidDefinitionError = Class.new(StandardError)
|
8
8
|
|
9
|
-
|
9
|
+
class UnexpectedMethodDefinitionError < InvalidDefinitionError
|
10
|
+
attr_reader :name
|
11
|
+
attr_reader :definition
|
12
|
+
|
13
|
+
def initialize(name, definition)
|
14
|
+
super("Expected lambda for method '#{name}' definition, got: #{definition.class.name}")
|
15
|
+
@name = name
|
16
|
+
@definition = definition
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class UndefinedMethodError < InvalidDefinitionError
|
21
|
+
attr_reader :name
|
22
|
+
|
23
|
+
def initialize(name)
|
24
|
+
super("Method '#{name}' does not exists")
|
25
|
+
@name = name
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
InvalidSchemaError = Class.new(InvalidDefinitionError)
|
10
30
|
|
11
31
|
CustomRequestError = Class.new(StandardError)
|
12
32
|
|
33
|
+
InvalidMultiAuthDefinition = Class.new(InvalidDefinitionError)
|
34
|
+
|
35
|
+
class UnresolvedMultiAuthOptionError < InvalidMultiAuthDefinition
|
36
|
+
attr_reader :name
|
37
|
+
|
38
|
+
def initialize(name)
|
39
|
+
super("Cannot find multi-auth definition for '#{name}'")
|
40
|
+
@name = name
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
13
44
|
RuntimeError = Class.new(StandardError)
|
14
45
|
|
46
|
+
class UnresolvedObjectDefinitionError < StandardError
|
47
|
+
attr_reader :name
|
48
|
+
|
49
|
+
def initialize(name)
|
50
|
+
super("Cannot find object definition for '#{name}'")
|
51
|
+
@name = name
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class CircleReferenceObjectDefinitionError < StandardError
|
56
|
+
attr_reader :name
|
57
|
+
|
58
|
+
def initialize(name, backtrace = [])
|
59
|
+
super("Infinite recursion occurred in object definition for '#{name}'")
|
60
|
+
set_backtrace(backtrace)
|
61
|
+
@name = name
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
15
65
|
class RequestError < StandardError
|
16
66
|
attr_reader :method
|
17
67
|
attr_reader :code
|
@@ -41,6 +91,24 @@ module Workato
|
|
41
91
|
super(message)
|
42
92
|
end
|
43
93
|
end
|
94
|
+
|
95
|
+
RequestTLSCertificateFormatError = Class.new(StandardError)
|
96
|
+
|
97
|
+
RequestPayloadFormatError = Class.new(StandardError)
|
98
|
+
|
99
|
+
JSONRequestFormatError = Class.new(RequestPayloadFormatError)
|
100
|
+
|
101
|
+
JSONResponseFormatError = Class.new(RequestPayloadFormatError)
|
102
|
+
|
103
|
+
XMLRequestFormatError = Class.new(RequestPayloadFormatError)
|
104
|
+
|
105
|
+
XMLResponseFormatError = Class.new(RequestPayloadFormatError)
|
106
|
+
|
107
|
+
WWWFormURLEncodedRequestFormatError = Class.new(RequestPayloadFormatError)
|
108
|
+
|
109
|
+
MultipartFormRequestFormatError = Class.new(RequestPayloadFormatError)
|
110
|
+
|
111
|
+
RAWResponseFormatError = Class.new(RequestPayloadFormatError)
|
44
112
|
end
|
45
113
|
end
|
46
114
|
end
|
@@ -4,6 +4,8 @@
|
|
4
4
|
require 'csv'
|
5
5
|
require 'singleton'
|
6
6
|
|
7
|
+
using Workato::Extension::HashWithIndifferentAccess
|
8
|
+
|
7
9
|
module Workato
|
8
10
|
module Connector
|
9
11
|
module Sdk
|
@@ -40,7 +42,7 @@ module Workato
|
|
40
42
|
@table_by_id ||= {}
|
41
43
|
@table_by_name ||= {}
|
42
44
|
data.each do |name, table|
|
43
|
-
table = table
|
45
|
+
table = HashWithIndifferentAccess.wrap(table)
|
44
46
|
rows = table['rows'].freeze
|
45
47
|
@table_by_id[table['id'].to_i] = rows
|
46
48
|
@table_by_name[name] = rows
|
@@ -18,16 +18,22 @@ module Workato
|
|
18
18
|
|
19
19
|
def lazy(settings = nil, config_fields = {})
|
20
20
|
DupHashWithIndifferentAccess.new do |object_definitions, name|
|
21
|
-
fields_proc = object_definitions_source
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
21
|
+
fields_proc = object_definitions_source.dig(name, :fields)
|
22
|
+
raise Workato::Connector::Sdk::UnresolvedObjectDefinitionError, name unless fields_proc
|
23
|
+
|
24
|
+
begin
|
25
|
+
object_definitions[name] = Action.new(
|
26
|
+
action: {
|
27
|
+
execute: lambda do |connection, input|
|
28
|
+
instance_exec(connection, input, object_definitions, &fields_proc)
|
29
|
+
end
|
30
|
+
},
|
31
|
+
methods: methods_source,
|
32
|
+
connection: connection
|
33
|
+
).execute(settings, config_fields)
|
34
|
+
rescue SystemStackError => e
|
35
|
+
raise Workato::Connector::Sdk::CircleReferenceObjectDefinitionError.new(name, e.backtrace)
|
36
|
+
end
|
31
37
|
end
|
32
38
|
end
|
33
39
|
|
@@ -5,6 +5,8 @@ require_relative './dsl'
|
|
5
5
|
require_relative './block_invocation_refinements'
|
6
6
|
require_relative './schema'
|
7
7
|
|
8
|
+
using Workato::Extension::HashWithIndifferentAccess
|
9
|
+
|
8
10
|
module Workato
|
9
11
|
module Connector
|
10
12
|
module Sdk
|
@@ -45,6 +47,7 @@ module Workato
|
|
45
47
|
include Dsl::HTTP
|
46
48
|
include Dsl::Call
|
47
49
|
include Dsl::Error
|
50
|
+
include Dsl::ExecutionContext
|
48
51
|
|
49
52
|
using BlockInvocationRefinements
|
50
53
|
|
@@ -57,8 +60,8 @@ module Workato
|
|
57
60
|
).void
|
58
61
|
end
|
59
62
|
def initialize(operation: {}, methods: {}, connection: Connection.new, object_definitions: nil)
|
60
|
-
@operation = T.let(operation
|
61
|
-
@_methods = T.let(methods
|
63
|
+
@operation = T.let(HashWithIndifferentAccess.wrap(operation), HashWithIndifferentAccess)
|
64
|
+
@_methods = T.let(HashWithIndifferentAccess.wrap(methods), HashWithIndifferentAccess)
|
62
65
|
@connection = T.let(connection, Connection)
|
63
66
|
@object_definitions = T.let(object_definitions, T.nilable(ObjectDefinitions))
|
64
67
|
end
|
@@ -80,13 +83,14 @@ module Workato
|
|
80
83
|
connection.merge_settings!(settings) if settings
|
81
84
|
request_or_result = T.unsafe(self).instance_exec(
|
82
85
|
connection.settings,
|
83
|
-
input
|
84
|
-
Array.wrap(extended_input_schema).map(
|
85
|
-
Array.wrap(extended_output_schema).map(
|
86
|
-
continue
|
86
|
+
HashWithIndifferentAccess.wrap(input),
|
87
|
+
Array.wrap(extended_input_schema).map { |i| HashWithIndifferentAccess.wrap(i) },
|
88
|
+
Array.wrap(extended_output_schema).map { |i| HashWithIndifferentAccess.wrap(i) },
|
89
|
+
HashWithIndifferentAccess.wrap(continue),
|
87
90
|
&block
|
88
91
|
)
|
89
|
-
resolve_request(request_or_result)
|
92
|
+
result = resolve_request(request_or_result)
|
93
|
+
try_convert_to_hash_with_indifferent_access(result)
|
90
94
|
end
|
91
95
|
|
92
96
|
sig do
|
@@ -225,7 +229,7 @@ module Workato
|
|
225
229
|
end
|
226
230
|
end
|
227
231
|
when ::Hash
|
228
|
-
request_or_result.inject(request_or_result
|
232
|
+
request_or_result.inject(request_or_result) do |acc, (key, value)|
|
229
233
|
response_value = resolve_request(value)
|
230
234
|
if response_value.equal?(value)
|
231
235
|
acc
|
@@ -238,6 +242,18 @@ module Workato
|
|
238
242
|
end
|
239
243
|
end
|
240
244
|
|
245
|
+
sig { params(value: T.untyped).returns(T.untyped) }
|
246
|
+
def try_convert_to_hash_with_indifferent_access(value)
|
247
|
+
case value
|
248
|
+
when ::Hash
|
249
|
+
HashWithIndifferentAccess.wrap(value)
|
250
|
+
when ::Array
|
251
|
+
value.map! { |i| try_convert_to_hash_with_indifferent_access(i) }
|
252
|
+
else
|
253
|
+
value
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
241
257
|
sig { returns(ObjectDefinitions) }
|
242
258
|
def object_definitions
|
243
259
|
T.must(@object_definitions)
|
@@ -8,8 +8,12 @@ require 'gyoku'
|
|
8
8
|
require 'net/http'
|
9
9
|
require 'net/http/digest_auth'
|
10
10
|
|
11
|
+
require 'workato/utilities/encoding'
|
12
|
+
require 'workato/utilities/xml'
|
11
13
|
require_relative './block_invocation_refinements'
|
12
14
|
|
15
|
+
using Workato::Extension::HashWithIndifferentAccess
|
16
|
+
|
13
17
|
module Workato
|
14
18
|
module Connector
|
15
19
|
module Sdk
|
@@ -27,10 +31,10 @@ module Workato
|
|
27
31
|
@action = action
|
28
32
|
@headers = {}
|
29
33
|
@case_sensitive_headers = {}
|
30
|
-
@params = {}.with_indifferent_access
|
31
34
|
@render_request = ->(payload) { payload }
|
32
35
|
@parse_response = ->(payload) { payload }
|
33
36
|
@after_response = ->(_response_code, parsed_response, _response_headers) { parsed_response }
|
37
|
+
@callstack_before_request = Array.wrap(Kernel.caller)
|
34
38
|
end
|
35
39
|
|
36
40
|
def method_missing(*args, &block)
|
@@ -38,36 +42,24 @@ module Workato
|
|
38
42
|
end
|
39
43
|
|
40
44
|
def execute!
|
41
|
-
__getobj__ || __setobj__(
|
42
|
-
authorized do
|
43
|
-
begin
|
44
|
-
request = build_request
|
45
|
-
response = execute(request)
|
46
|
-
rescue RestClient::Unauthorized => e
|
47
|
-
Kernel.raise e unless @digest_auth
|
48
|
-
|
49
|
-
@digest_auth = false
|
50
|
-
headers('Authorization' => Net::HTTP::DigestAuth.new.auth_header(
|
51
|
-
URI.parse(build_url),
|
52
|
-
e.response.headers[:www_authenticate],
|
53
|
-
method.to_s.upcase
|
54
|
-
))
|
55
|
-
request = build_request
|
56
|
-
response = execute(request)
|
57
|
-
end
|
58
|
-
detect_error!(response.body)
|
59
|
-
parsed_response = @parse_response.call(response)
|
60
|
-
detect_error!(parsed_response)
|
61
|
-
within_action_context(response.code, parsed_response, response.headers, &@after_response)
|
62
|
-
end
|
63
|
-
)
|
45
|
+
__getobj__ || __setobj__(response)
|
64
46
|
rescue RestClient::Exception => e
|
65
47
|
if after_error_response_matches?(e)
|
66
48
|
return apply_after_error_response(e)
|
67
49
|
end
|
68
50
|
|
69
|
-
Kernel.raise RequestError.new(
|
70
|
-
|
51
|
+
Kernel.raise RequestError.new(
|
52
|
+
response: e.response,
|
53
|
+
message: e.message,
|
54
|
+
method: current_verb,
|
55
|
+
code: e.http_code
|
56
|
+
)
|
57
|
+
rescue StandardError => e
|
58
|
+
error_backtrace = Array.wrap(e.backtrace)
|
59
|
+
first_call_after_request_idx = error_backtrace.rindex { |s| s.start_with?(__FILE__) }
|
60
|
+
error_backtrace_after_request = error_backtrace[0..first_call_after_request_idx]
|
61
|
+
e.set_backtrace(error_backtrace_after_request + @callstack_before_request)
|
62
|
+
Kernel.raise e
|
71
63
|
end
|
72
64
|
|
73
65
|
def headers(headers)
|
@@ -81,7 +73,12 @@ module Workato
|
|
81
73
|
end
|
82
74
|
|
83
75
|
def params(params)
|
84
|
-
|
76
|
+
if params.is_a?(Hash)
|
77
|
+
@params ||= HashWithIndifferentAccess.new
|
78
|
+
@params.merge!(params)
|
79
|
+
else
|
80
|
+
@params = params
|
81
|
+
end
|
85
82
|
self
|
86
83
|
end
|
87
84
|
|
@@ -142,13 +139,17 @@ module Workato
|
|
142
139
|
|
143
140
|
def request_format_json
|
144
141
|
@content_type_header = :json
|
145
|
-
@render_request =
|
142
|
+
@render_request = lambda_with_error_wrap(JSONRequestFormatError) do |payload|
|
143
|
+
ActiveSupport::JSON.encode(payload) if payload
|
144
|
+
end
|
146
145
|
self
|
147
146
|
end
|
148
147
|
|
149
148
|
def response_format_json
|
150
149
|
@accept_header = :json
|
151
|
-
@parse_response =
|
150
|
+
@parse_response = lambda_with_error_wrap(JSONResponseFormatError) do |payload|
|
151
|
+
ActiveSupport::JSON.decode(payload.presence || '{}')
|
152
|
+
end
|
152
153
|
self
|
153
154
|
end
|
154
155
|
|
@@ -158,17 +159,19 @@ module Workato
|
|
158
159
|
|
159
160
|
def request_format_xml(root_element_name, namespaces = {})
|
160
161
|
@content_type_header = :xml
|
161
|
-
@render_request =
|
162
|
+
@render_request = lambda_with_error_wrap(XMLRequestFormatError) do |payload|
|
162
163
|
next unless payload
|
163
164
|
|
164
165
|
Gyoku.xml({ root_element_name => payload.merge(namespaces).deep_symbolize_keys }, key_converter: :none)
|
165
|
-
|
166
|
+
end
|
166
167
|
self
|
167
168
|
end
|
168
169
|
|
169
170
|
def response_format_xml(strip_response_namespaces: false)
|
170
171
|
@accept_header = :xml
|
171
|
-
@parse_response =
|
172
|
+
@parse_response = lambda_with_error_wrap(XMLResponseFormatError) do |payload|
|
173
|
+
Workato::Utilities::Xml.parse_xml_to_hash(payload, strip_namespaces: strip_response_namespaces)
|
174
|
+
end
|
172
175
|
self
|
173
176
|
end
|
174
177
|
|
@@ -179,7 +182,7 @@ module Workato
|
|
179
182
|
end
|
180
183
|
|
181
184
|
def response_format_raw
|
182
|
-
@parse_response =
|
185
|
+
@parse_response = lambda_with_error_wrap(RAWResponseFormatError) do |payload|
|
183
186
|
payload.body.force_encoding(::Encoding::BINARY)
|
184
187
|
payload.body.valid_encoding? ? payload.body : payload.body.force_encoding(::Encoding::BINARY)
|
185
188
|
end
|
@@ -189,7 +192,7 @@ module Workato
|
|
189
192
|
def request_format_multipart_form
|
190
193
|
@content_type_header = nil
|
191
194
|
|
192
|
-
@render_request =
|
195
|
+
@render_request = lambda_with_error_wrap(MultipartFormRequestFormatError) do |payload|
|
193
196
|
payload&.each_with_object({}) do |(name, (value, content_type, original_filename)), rendered|
|
194
197
|
rendered[name] = if content_type.present?
|
195
198
|
Part.new(name, content_type, original_filename || ::File.basename(name), value.to_s)
|
@@ -204,7 +207,7 @@ module Workato
|
|
204
207
|
|
205
208
|
def request_format_www_form_urlencoded
|
206
209
|
@content_type_header = 'application/x-www-form-urlencoded'
|
207
|
-
@render_request =
|
210
|
+
@render_request = lambda_with_error_wrap(WWWFormURLEncodedRequestFormatError, &:to_param)
|
208
211
|
self
|
209
212
|
end
|
210
213
|
|
@@ -228,6 +231,8 @@ module Workato
|
|
228
231
|
OpenSSL::X509::Certificate.new(intermediate)
|
229
232
|
end
|
230
233
|
self
|
234
|
+
rescue OpenSSL::OpenSSLError => e
|
235
|
+
Kernel.raise(RequestTLSCertificateFormatError, e)
|
231
236
|
end
|
232
237
|
|
233
238
|
def tls_server_certs(certificates:, strict: true)
|
@@ -237,17 +242,47 @@ module Workato
|
|
237
242
|
@ssl_cert_store.add_cert(OpenSSL::X509::Certificate.new(certificate))
|
238
243
|
end
|
239
244
|
self
|
245
|
+
rescue OpenSSL::OpenSSLError => e
|
246
|
+
Kernel.raise(RequestTLSCertificateFormatError, e)
|
240
247
|
end
|
241
248
|
|
242
249
|
def puts(*args)
|
243
250
|
::Kernel.puts(*args)
|
244
251
|
end
|
245
252
|
|
253
|
+
def try(*args, &block)
|
254
|
+
execute!.try(*args, &block)
|
255
|
+
end
|
256
|
+
|
246
257
|
private
|
247
258
|
|
248
259
|
attr_reader :method
|
249
260
|
|
250
|
-
def
|
261
|
+
def response
|
262
|
+
authorized do
|
263
|
+
begin
|
264
|
+
request = RestClientRequest.new(rest_request_params)
|
265
|
+
response = execute_request(request)
|
266
|
+
rescue RestClient::Unauthorized => e
|
267
|
+
Kernel.raise e unless @digest_auth
|
268
|
+
|
269
|
+
@digest_auth = false
|
270
|
+
headers('Authorization' => Net::HTTP::DigestAuth.new.auth_header(
|
271
|
+
URI.parse(build_url),
|
272
|
+
e.response.headers[:www_authenticate],
|
273
|
+
method.to_s.upcase
|
274
|
+
))
|
275
|
+
request = RestClientRequest.new(rest_request_params)
|
276
|
+
response = execute_request(request)
|
277
|
+
end
|
278
|
+
detect_error!(response.body)
|
279
|
+
parsed_response = @parse_response.call(response)
|
280
|
+
detect_error!(parsed_response)
|
281
|
+
apply_after_response(response.code, parsed_response, response.headers)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def execute_request(request)
|
251
286
|
if @follow_redirection.nil?
|
252
287
|
request.execute
|
253
288
|
else
|
@@ -266,25 +301,22 @@ module Workato
|
|
266
301
|
end
|
267
302
|
end
|
268
303
|
|
269
|
-
def
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
304
|
+
def rest_request_params
|
305
|
+
{
|
306
|
+
method: method,
|
307
|
+
url: build_url,
|
308
|
+
headers: build_headers,
|
309
|
+
payload: @render_request.call(@payload),
|
310
|
+
case_sensitive_headers: @case_sensitive_headers.transform_keys(&:to_s)
|
311
|
+
}.tap do |request_hash|
|
312
|
+
if @ssl_client_cert.present? && @ssl_client_key.present?
|
313
|
+
request_hash[:ssl_client_cert] = @ssl_client_cert
|
314
|
+
request_hash[:ssl_client_key] = @ssl_client_key
|
315
|
+
if @ssl_client_intermediate_certs.present?
|
316
|
+
request_hash[:ssl_extra_chain_cert] = @ssl_client_intermediate_certs
|
280
317
|
end
|
281
|
-
request_hash[:ssl_cert_store] = @ssl_cert_store if @ssl_cert_store
|
282
|
-
end
|
283
|
-
).tap do |request|
|
284
|
-
request.case_sensitive_headers = @case_sensitive_headers.transform_keys(&:to_s)
|
285
|
-
if @ssl_client_intermediate_certs.present? && @ssl_client_cert.present? && @ssl_client_key.present?
|
286
|
-
request.extra_chain_cert = @ssl_client_intermediate_certs
|
287
318
|
end
|
319
|
+
request_hash[:ssl_cert_store] = @ssl_cert_store if @ssl_cert_store
|
288
320
|
end
|
289
321
|
end
|
290
322
|
|
@@ -295,14 +327,14 @@ module Workato
|
|
295
327
|
URI.parse(@uri)
|
296
328
|
end
|
297
329
|
|
298
|
-
return uri.to_s unless @params
|
330
|
+
return uri.to_s unless @params || @user || @password
|
299
331
|
|
300
332
|
unless @digest_auth
|
301
333
|
uri.user = URI.encode_www_form_component(@user) if @user
|
302
334
|
uri.password = URI.encode_www_form_component(@password) if @password
|
303
335
|
end
|
304
336
|
|
305
|
-
return uri.to_s unless @params
|
337
|
+
return uri.to_s unless @params
|
306
338
|
|
307
339
|
query = uri.query.to_s.split('&').select(&:present?).join('&').presence
|
308
340
|
params = @params.to_param.presence
|
@@ -354,12 +386,19 @@ module Workato
|
|
354
386
|
within_action_context(
|
355
387
|
exception.http_code,
|
356
388
|
exception.http_body,
|
357
|
-
exception.http_headers
|
389
|
+
HashWithIndifferentAccess.wrap(exception.http_headers),
|
358
390
|
exception.message,
|
359
391
|
&@after_error_response
|
360
392
|
)
|
361
393
|
end
|
362
394
|
|
395
|
+
def apply_after_response(code, parsed_response, headers)
|
396
|
+
encoded_headers = (headers || {}).each_with_object(HashWithIndifferentAccess.new) do |(k, v), h|
|
397
|
+
h[k] = Workato::Utilities::Encoding.force_best_encoding!(v.to_s)
|
398
|
+
end
|
399
|
+
within_action_context(code, parsed_response, encoded_headers, &@after_response)
|
400
|
+
end
|
401
|
+
|
363
402
|
def within_action_context(*args, &block)
|
364
403
|
(@action || self).instance_exec(*args, &block)
|
365
404
|
end
|
@@ -378,13 +417,13 @@ module Workato
|
|
378
417
|
first = true
|
379
418
|
begin
|
380
419
|
settings = connection.settings
|
381
|
-
if
|
420
|
+
if connection.authorization.oauth2?
|
382
421
|
instance_exec(settings, settings[:access_token], @auth_type, &apply)
|
383
422
|
else
|
384
423
|
instance_exec(settings, @auth_type, &apply)
|
385
424
|
end
|
386
425
|
yield
|
387
|
-
rescue
|
426
|
+
rescue RestClient::Exception, CustomRequestError => e
|
388
427
|
Kernel.raise e unless first
|
389
428
|
Kernel.raise e unless refresh_authorization!(e.try(:http_code), e.try(:http_body), e.message)
|
390
429
|
|
@@ -413,6 +452,16 @@ module Workato
|
|
413
452
|
T.must(@connection)
|
414
453
|
end
|
415
454
|
|
455
|
+
def lambda_with_error_wrap(error_type, &block)
|
456
|
+
Kernel.lambda do |payload|
|
457
|
+
begin
|
458
|
+
block.call(payload)
|
459
|
+
rescue StandardError => e
|
460
|
+
Kernel.raise error_type.new(e)
|
461
|
+
end
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
416
465
|
class Part < StringIO
|
417
466
|
def initialize(path, content_type, original_filename, *args)
|
418
467
|
super(*args)
|
@@ -425,6 +474,35 @@ module Workato
|
|
425
474
|
attr_reader :content_type
|
426
475
|
attr_reader :original_filename
|
427
476
|
end
|
477
|
+
|
478
|
+
class RestClientRequest < ::RestClient::Request
|
479
|
+
def initialize(args)
|
480
|
+
super
|
481
|
+
@ssl_opts[:extra_chain_cert] = args[:ssl_extra_chain_cert] if args.key?(:ssl_extra_chain_cert)
|
482
|
+
@case_sensitive_headers = args[:case_sensitive_headers]
|
483
|
+
@before_execution_proc = proc do |net_http_request, _args|
|
484
|
+
net_http_request.case_sensitive_headers = args[:case_sensitive_headers]
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
def ssl_extra_chain_cert
|
489
|
+
@ssl_opts[:extra_chain_cert]
|
490
|
+
end
|
491
|
+
|
492
|
+
def processed_headers
|
493
|
+
return @processed_headers if @case_sensitive_headers.blank?
|
494
|
+
return @case_sensitive_headers if @processed_headers.blank?
|
495
|
+
|
496
|
+
@processed_headers.merge(@case_sensitive_headers)
|
497
|
+
end
|
498
|
+
|
499
|
+
def net_http_object(hostname, port)
|
500
|
+
net = super(hostname, port)
|
501
|
+
net.extra_chain_cert = ssl_extra_chain_cert if ssl_extra_chain_cert
|
502
|
+
net
|
503
|
+
end
|
504
|
+
end
|
505
|
+
private_constant :RestClientRequest
|
428
506
|
end
|
429
507
|
end
|
430
508
|
end
|
@@ -1,20 +1,22 @@
|
|
1
1
|
# typed: false
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
using Workato::Extension::HashWithIndifferentAccess
|
5
|
+
|
4
6
|
module Workato
|
5
7
|
module Connector
|
6
8
|
module Sdk
|
7
9
|
class Schema < SimpleDelegator
|
8
10
|
def initialize(schema: [])
|
9
|
-
super(Fields.new(::Array.wrap(schema).map(
|
11
|
+
super(Fields.new(::Array.wrap(schema).map { |i| HashWithIndifferentAccess.wrap(i) }))
|
10
12
|
end
|
11
13
|
|
12
14
|
def trim(input)
|
13
|
-
input.
|
15
|
+
HashWithIndifferentAccess.wrap(input).keep_if { |property_name| includes_property?(property_name) }
|
14
16
|
end
|
15
17
|
|
16
18
|
def apply(input, enforce_required:, &block)
|
17
|
-
input.
|
19
|
+
HashWithIndifferentAccess.wrap(input).tap do |input_with_indifferent_access|
|
18
20
|
apply_to_hash(self, input_with_indifferent_access, enforce_required: enforce_required, &block)
|
19
21
|
end
|
20
22
|
end
|