tencentcloud-sdk-common 1.0.199

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 860333f84b5b6c07088a6348b3e9998f5ca736cf
4
+ data.tar.gz: d954ff249bf9164d8fd2d5938966f44377019f30
5
+ SHA512:
6
+ metadata.gz: 6d96a82ccd871524957bc4db9fa26c5471641a7e4c8690d0e29a06d1b959e8be00fc5f17e913b6fe910f458c7ed225aaac7b3a38ef5c9e1923ef61d9554905c8
7
+ data.tar.gz: 6a9917086e1bc39178c0a117c7bad59e248e172f3cd5a46b98d174891a8db535b848279a9cfbcb3cee74a429f9a682936a367b215a6f6c3c89dd54fc62d887ef
data/lib/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.199
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'time'
4
+ require 'uri'
5
+ require 'json'
6
+ require 'securerandom'
7
+ require 'digest'
8
+
9
+ module TencentCloud
10
+ module Common
11
+ # common client
12
+ class AbstractClient
13
+ include Log
14
+
15
+ def initialize(credential, region, api_version, api_endpoint, sdk_version, profile = nil)
16
+ raise TencentCloudSDKException.new('InvalidCredential', 'Credential is None or invalid') unless credential
17
+
18
+ @credential = credential
19
+ @region = region
20
+ @api_version = api_version
21
+ @endpoint = api_endpoint
22
+ @sdk_version = sdk_version
23
+ @profile = profile || ClientProfile.new
24
+ @request = ApiRequset.new(@profile.http_profile.scheme, endpoint, nil, @profile.http_profile.req_timeout, @profile.http_profile.proxy)
25
+ end
26
+
27
+ def send_request(action, params, options = {})
28
+ request_data = BaseRequest.new(@profile.http_profile.scheme, endpoint, @profile.http_profile.req_method, REQUEST_PATH)
29
+ build_req(action, params, request_data, options)
30
+ logger.debug("Request: [\n#{request_data.to_s}]") if @profile.debug
31
+ resp = @request.send_request(request_data)
32
+ logger.debug("Response: [\n#{resp.to_s}]") if @profile.debug
33
+ raise TencentCloudSDKException.new('ServerNetworkError', resp.data) if resp.code != '200'
34
+
35
+ resp.data
36
+ end
37
+
38
+ private
39
+
40
+ REQUEST_PATH = '/'
41
+ JSON_CONTENT = 'application/json'
42
+ MULTIPART_CONTENT = 'multipart/form-data'
43
+ FORM_URLENCODED_CONTENT = 'application/x-www-form-urlencoded'
44
+
45
+ def endpoint
46
+ @profile.http_profile.endpoint || @endpoint
47
+ end
48
+
49
+ def build_req(action, params, req, options = {})
50
+ if %w[HmacSHA1 HmacSHA256].include? @profile.sign_method
51
+ build_req_with_v1_signature(action, params, req)
52
+ elsif @profile.sign_method == 'TC3-HMAC-SHA256' || options['IsMultipart']
53
+ build_req_with_v3_signature(action, params, req, options)
54
+ else
55
+ raise TencentCloudSDKException.new('ClientError', 'Invalid signature method')
56
+ end
57
+ end
58
+
59
+ def build_req_with_v1_signature(action, params, req)
60
+ params = AbstractModel.format_params(nil, params)
61
+ params['Action'] = action
62
+ params['RequestClient'] = "SDK_RUBY_#{@sdk_version}"
63
+ params['Nonce'] = Random.rand(1..1 << 32)
64
+ params['Timestamp'] = Time.now.to_i
65
+ params['Version'] = @api_version
66
+ params['Region'] = @region
67
+ params['Token'] = @credential.token if @credential.token
68
+ params['SecretId'] = @credential.secret_id
69
+ params['SignatureMethod'] = @profile.sign_method
70
+ params['Language'] = @profile.language
71
+ params['Signature'] = Sign.sign_v1(@profile.http_profile.req_method, endpoint, req.uri,
72
+ params, @credential.secret_key, @profile.sign_method)
73
+ req.data = URI.encode_www_form(params)
74
+ req.header['Content-Type'] = FORM_URLENCODED_CONTENT
75
+ end
76
+
77
+ def build_req_with_v3_signature(action, params, req, options = {})
78
+ content_type = req.method == 'GET' ? FORM_URLENCODED_CONTENT : JSON_CONTENT
79
+ content_type = MULTIPART_CONTENT if options['IsMultipart']
80
+ timestamp = Time.now.to_i
81
+ req.header['Content-Type'] = content_type
82
+ req.header['Host'] = endpoint
83
+ req.header['X-TC-Action'] = action
84
+ req.header['X-TC-Timestamp'] = timestamp
85
+ req.header['X-TC-Version'] = @api_version
86
+ req.header['X-TC-Region'] = @region
87
+ req.header['X-TC-Language'] = @profile.language
88
+ req.header['X-TC-Token'] = @credential.token if @credential.token
89
+ req.header['X-TC-Content-SHA256'] = 'UNSIGNED-PAYLOAD' if @profile.unsigned_payload
90
+ if req.method == 'GET'
91
+ params = AbstractModel.format_params(nil, params)
92
+ req.data = URI.encode_www_form(params)
93
+ canonical_querystring = req.data
94
+ payload = ''
95
+ else
96
+ case content_type
97
+ when JSON_CONTENT
98
+ req.data = JSON.generate(params, { 'ascii_only' => true, 'space' => ' ' })
99
+ when MULTIPART_CONTENT
100
+ binparas = options['binparas'] || []
101
+ boundary = SecureRandom.hex
102
+ req.header['Content-Type'] += '; boundary=' + boundary
103
+ body = ''
104
+ params.each do |k, v|
105
+ body += "--#{boundary}\r\n"
106
+ body += "Content-Disposition: form-data; name=\"#{k}\""
107
+ if binparas.include? k
108
+ body += "; filename=\"File\"\r\n"
109
+ else
110
+ body += "\r\n"
111
+ if v.is_a?(Array) || v.is_a?(Hash)
112
+ v = JSON.generate(v, { 'ascii_only' => true, 'space' => ' ' })
113
+ body += "Content-Type: application/json\r\n"
114
+ end
115
+ end
116
+ body += "\r\n#{v}\r\n"
117
+ end
118
+ body += "--#{boundary}--\r\n" unless body.empty?
119
+ req.data = body
120
+ # req.is_multipart = options['IsMultipart']
121
+ else
122
+ raise TencentCloudSDKException.new('ContentTypeError', "Unsupported content type: #{content_type}")
123
+ end
124
+ payload = req.data
125
+ canonical_querystring = ''
126
+ end
127
+ payload = 'UNSIGNED-PAYLOAD' if @profile.unsigned_payload
128
+ hashed_payload = Digest::SHA256.hexdigest(payload)
129
+
130
+ authorization = Sign.sign_v3(content_type, endpoint, @profile.http_profile.req_method, req.uri,
131
+ canonical_querystring, hashed_payload, req.header['X-TC-Timestamp'],
132
+ @credential.secret_id, @credential.secret_key)
133
+ req.header['Authorization'] = authorization
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TencentCloud
4
+ module Common
5
+ # common credential
6
+ class Credential
7
+ attr_accessor :secret_id, :secret_key, :token
8
+
9
+ def initialize(secret_id, secret_key, token = nil)
10
+ if secret_id.nil? || secret_id.strip.empty?
11
+ raise TencentCloudSDKException.new('InvalidCredential', 'secret id should not be none or empty')
12
+ elsif secret_id.strip != secret_id
13
+ raise TencentCloudSDKException.new('InvalidCredential', 'secret id should not contain spaces')
14
+ end
15
+
16
+ @secret_id = secret_id
17
+
18
+ if secret_key.nil? || secret_key.strip.empty?
19
+ raise TencentCloudSDKException.new('InvalidCredential', 'secret id should not be none or empty')
20
+ elsif secret_key.strip != secret_key
21
+ raise TencentCloudSDKException.new('InvalidCredential', 'secret id should not contain spaces')
22
+ end
23
+
24
+ @secret_key = secret_key
25
+ @token = token
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TencentCloud
4
+ module Common
5
+ # TencentCloud exception
6
+ class TencentCloudSDKException < StandardError
7
+ attr_accessor :code, :message, :request_id
8
+
9
+ def initialize(code = nil, message = nil, request_id = nil)
10
+ @code = code
11
+ @message = message
12
+ @request_id = request_id
13
+ end
14
+
15
+ def to_s
16
+ "[TencentCloudSDKError] Code=#{@code}, Message=#{@message}, RequestId=#{@request_id}"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require 'net/http'
5
+
6
+ module TencentCloud
7
+ module Common
8
+ # common http request class
9
+ class ApiRequset
10
+ def initialize(scheme, host, port = nil, timeout = 60, proxy = nil)
11
+ port = 443 if scheme == 'https'
12
+ if proxy.nil?
13
+ @conn = Net::HTTP.new(host, port)
14
+ else
15
+ p = URI(proxy)
16
+ @conn = Net::HTTP.new(host, port, p.host, p.port, p.user, p.pass)
17
+ end
18
+ @conn.use_ssl = scheme == 'https'
19
+ @conn.read_timeout = timeout
20
+ end
21
+
22
+ def send_request(request, keep_alive = false)
23
+ uri = URI("#{request.scheme}://#{request.host}#{request.uri}")
24
+ @conn.keep_alive_timeout = 20 if keep_alive
25
+ @conn.start do |http|
26
+ case request.method
27
+ when 'GET'
28
+ uri.query = request.data
29
+ req = Net::HTTP::Get.new uri
30
+ when 'POST'
31
+ req = Net::HTTP::Post.new uri
32
+ req.body = request.data
33
+ else
34
+ raise TencentCloudSDKException.new('ClientParamsError', 'Method only support (GET, POST)')
35
+ end
36
+ request.header.each do |k, v|
37
+ req[k] = v
38
+ end
39
+ resp = http.request req
40
+ BaseResponse.new(resp.code, resp.each_header.to_h, resp.read_body)
41
+ end
42
+ end
43
+ end
44
+
45
+ # base class of http request data
46
+ class BaseRequest
47
+ attr_accessor :scheme, :host, :method, :uri, :header, :data, :is_multipart
48
+
49
+ def initialize(scheme = '', host = '', method = '', uri = '', header = {}, data = nil)
50
+ @scheme = scheme
51
+ @host = host
52
+ @method = method
53
+ @uri = uri
54
+ @header = header
55
+ @data = data
56
+ @is_multipart = false
57
+ end
58
+
59
+ def to_s
60
+ s = "Host: #{@host}\nMethod: #{method}\nUri: #{@uri}\nHeader: \n"
61
+ @header ||= {}
62
+ @header.each do |k, v|
63
+ s += "#{k}: #{v}\n"
64
+ end
65
+ s += "Data: #{@data}\n"
66
+ end
67
+ end
68
+
69
+ # base class of http response data
70
+ class BaseResponse
71
+ attr_accessor :code, :header, :data
72
+
73
+ def initialize(code = 200, header = nil, data = "")
74
+ @code = code
75
+ @header = header
76
+ @data = data
77
+ end
78
+
79
+ def to_s
80
+ s = "Status: #{@code}\nHeader: \n"
81
+ @header ||= {}
82
+ @header.each do |k, v|
83
+ s += "#{k}: #{v}\n"
84
+ end
85
+ s += "Data: #{@data}\n"
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module TencentCloud
6
+ module Common
7
+ # common logger
8
+ module Log
9
+ def logger
10
+ @logger ||= Logger.new(STDOUT)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TencentCloud
4
+ module Common
5
+ # common model
6
+ class AbstractModel
7
+ def serialize
8
+ flat(self)
9
+ end
10
+
11
+ def self.format_params(prefix = nil, params)
12
+ d = {}
13
+ case params
14
+ when Hash
15
+ params.each do |k, v|
16
+ key = prefix ? "#{prefix}.#{k}" : k.to_s
17
+ d.update(format_params(key, v))
18
+ end
19
+ when Array
20
+ params.each_with_index do |v, i|
21
+ key = prefix ? "#{prefix}.#{i}" : i.to_s
22
+ d.update(format_params(key, v))
23
+ end
24
+ else
25
+ d[prefix] = params
26
+ end
27
+ d
28
+ end
29
+
30
+ private
31
+
32
+ def flat(obj)
33
+ case obj
34
+ when AbstractModel
35
+ params = nil
36
+ keys = obj.instance_variables
37
+ keys.each do |k|
38
+ value = obj.instance_variable_get k
39
+ key = k.to_s.split('@').at 1
40
+ next unless value
41
+
42
+ r = flat(value)
43
+ unless r.nil?
44
+ params ||= {}
45
+ params[key] = r
46
+ end
47
+ end
48
+ params
49
+ when Array
50
+ arr = nil
51
+ obj.each do |v|
52
+ r = flat(v)
53
+ unless r.nil?
54
+ arr ||= []
55
+ arr << r
56
+ end
57
+ end
58
+ arr
59
+ else
60
+ obj
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TencentCloud
4
+ module Common
5
+ # basic httpprofile
6
+ class ClientProfile
7
+ attr_accessor :http_profile, :sign_method, :language, :unsigned_payload, :debug
8
+
9
+ def initialize(sign_method = 'TC3-HMAC-SHA256', http_profile = nil,
10
+ language = 'zh-CN', debug = false)
11
+ @sign_method = sign_method
12
+ @http_profile = http_profile || HttpProfile.new
13
+ valid_language = %w[zh-CN en-US]
14
+ unless valid_language.include? language
15
+ raise TencentCloudSDKException.new('ClientError', "Language invalid, choices: #{valid_language}")
16
+ end
17
+
18
+ @language = language
19
+ @debug = debug
20
+ @unsigned_payload = false
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TencentCloud
4
+ module Common
5
+ # basic httpprofile
6
+ class HttpProfile
7
+ attr_accessor :scheme, :endpoint, :req_method, :req_timeout, :keep_alive, :proxy
8
+
9
+ def initialize(scheme = 'https', endpoint = nil, req_method = 'POST',
10
+ req_timeout = 60, keep_alive = false, proxy = nil)
11
+ @scheme = scheme
12
+ @endpoint = endpoint
13
+ @req_method = req_method
14
+ @req_timeout = req_timeout
15
+ @keep_alive = keep_alive
16
+ @proxy = proxy
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+ require 'base64'
5
+
6
+ module TencentCloud
7
+ module Common
8
+ # sign class
9
+ class Sign
10
+ class << self
11
+ def sign_v1(method, endpoint, path, data, secret_key, sign_method)
12
+ sign = method + endpoint + path + '?'
13
+ params = []
14
+ data.sort.each do |item|
15
+ params << "#{item[0]}=#{item[1]}"
16
+ end
17
+ sign += params.join('&')
18
+ case sign_method
19
+ when 'HmacSHA256'
20
+ digest = OpenSSL::Digest.new('sha256')
21
+ when 'HmacSHA1'
22
+ digest = OpenSSL::Digest.new('sha1')
23
+ else
24
+ raise TencentCloudSDKException.new('signMethod invalid', 'signMethod only support (HmacSHA1, HmacSHA256)')
25
+ end
26
+ Base64.encode64(OpenSSL::HMAC.digest(digest, secret_key, sign))
27
+ end
28
+
29
+ def sign_v3(content_type, endpoint, method, uri, query, payload, timestamp, secret_id, secret_key)
30
+ canonical_headers = "content-type:#{content_type}\nhost:#{endpoint}\n"
31
+ signed_headers = 'content-type;host'
32
+ canonical_request = [
33
+ method,
34
+ uri,
35
+ query,
36
+ canonical_headers,
37
+ signed_headers,
38
+ payload,
39
+ ].join("\n")
40
+ service = endpoint.split('.')[0]
41
+
42
+ date = Time.at(timestamp).utc.strftime('%Y-%m-%d')
43
+ credential_scope = date + '/' + service + '/' + 'tc3_request'
44
+ algorithm = 'TC3-HMAC-SHA256'
45
+ hashed_request_payload = Digest::SHA256.hexdigest(canonical_request)
46
+ string_to_sign = [
47
+ algorithm,
48
+ timestamp,
49
+ credential_scope,
50
+ hashed_request_payload,
51
+ ].join("\n")
52
+
53
+ digest = OpenSSL::Digest.new('sha256')
54
+ secret_date = OpenSSL::HMAC.digest(digest, 'TC3' + secret_key, date)
55
+ secret_service = OpenSSL::HMAC.digest(digest, secret_date, service)
56
+ secret_signing = OpenSSL::HMAC.digest(digest, secret_service, 'tc3_request')
57
+ signature = OpenSSL::HMAC.hexdigest(digest, secret_signing, string_to_sign)
58
+ "#{algorithm} Credential=#{secret_id}/#{credential_scope}, SignedHeaders=#{signed_headers}, Signature=#{signature}"
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'tencentcloud-sdk-common/exception'
4
+ require_relative 'tencentcloud-sdk-common/log'
5
+ require_relative 'tencentcloud-sdk-common/profile/client_profile'
6
+ require_relative 'tencentcloud-sdk-common/profile/http_profile'
7
+ require_relative 'tencentcloud-sdk-common/credential'
8
+ require_relative 'tencentcloud-sdk-common/models'
9
+ require_relative 'tencentcloud-sdk-common/sign'
10
+ require_relative 'tencentcloud-sdk-common/http/request'
11
+ require_relative 'tencentcloud-sdk-common/client'
12
+
13
+ module TencentCloud
14
+ # sdk common module
15
+ module Common
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tencentcloud-sdk-common
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.199
5
+ platform: ruby
6
+ authors:
7
+ - Tencent Cloud
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-11-11 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Tencent Cloud Ruby SDK is the official software development kit, which
14
+ allows Ruby developers to write software that makes use of Tencent Cloud service.
15
+ email:
16
+ - tencentcloudapi@tencent.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/VERSION
22
+ - lib/tencentcloud-sdk-common.rb
23
+ - lib/tencentcloud-sdk-common/client.rb
24
+ - lib/tencentcloud-sdk-common/credential.rb
25
+ - lib/tencentcloud-sdk-common/exception.rb
26
+ - lib/tencentcloud-sdk-common/http/request.rb
27
+ - lib/tencentcloud-sdk-common/log.rb
28
+ - lib/tencentcloud-sdk-common/models.rb
29
+ - lib/tencentcloud-sdk-common/profile/client_profile.rb
30
+ - lib/tencentcloud-sdk-common/profile/http_profile.rb
31
+ - lib/tencentcloud-sdk-common/sign.rb
32
+ homepage: https://github.com/TencentCloud/tencentcloud-sdk-ruby
33
+ licenses:
34
+ - Apache-2.0
35
+ metadata:
36
+ source_code_uri: https://github.com/TencentCloud/tencentcloud-sdk-ruby/tencentcloud-sdk-common
37
+ changelog_uri: https://github.com/TencentCloud/tencentcloud-sdk-ruby/blob/master/CHANGELOG.md
38
+ post_install_message:
39
+ rdoc_options: []
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project:
54
+ rubygems_version: 2.6.14
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Tencent Cloud SDK for Ruby - Common
58
+ test_files: []