tablestore-ruby-sdk 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ require 'tablestore/crc8_auto'
2
+
3
+ class PlainBufferCrc8
4
+ class << self
5
+ def crc_string(crc, bytes)
6
+ Digest::CRC8Auto.new.crc8(crc, bytes.to_s).checksum
7
+ end
8
+
9
+ def crc_int8(crc, byte)
10
+ Digest::CRC8Auto.new.crc8(crc, [byte].pack('C*')).checksum
11
+ end
12
+
13
+ def crc_int32(crc, byte)
14
+ Digest::CRC8Auto.new.crc8(crc, [byte].pack('i')).checksum
15
+ end
16
+
17
+ def crc_int64(crc, byte)
18
+ Digest::CRC8Auto.new.crc8(crc, [byte].pack('q')).checksum
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,92 @@
1
+ require 'tablestore/error'
2
+
3
+ class PlainBufferInputStream
4
+ def initialize(data_buffer)
5
+ @buffer = data_buffer
6
+ @cur_pos = 0
7
+ @last_tag = 0
8
+ end
9
+
10
+ def is_at_end?
11
+ @buffer.length == @cur_pos
12
+ end
13
+
14
+ def read_tag
15
+ if is_at_end?
16
+ @last_tag = 0
17
+ return 0
18
+ end
19
+ @last_tag = read_raw_byte
20
+ @last_tag.ord
21
+ end
22
+
23
+ def check_last_tag_was(tag)
24
+ @last_tag.ord == tag
25
+ end
26
+
27
+ def get_last_tag
28
+ @last_tag.ord
29
+ end
30
+
31
+ def read_raw_byte
32
+ raise TableStoreClientError.new("Read raw byte encountered EOF.") if is_at_end?
33
+ pos = @cur_pos
34
+ @cur_pos += 1
35
+ if @buffer[pos].is_a?(Fixnum)
36
+ [@buffer[pos]].chr
37
+ else
38
+ @buffer[pos]
39
+ end
40
+ end
41
+
42
+ def read_raw_little_endian64
43
+ read_bytes(8).unpack('q<')[0]
44
+ end
45
+
46
+ def read_raw_little_endian32
47
+ read_bytes(4).unpack('i<')[0]
48
+ end
49
+
50
+ def read_boolean
51
+ read_bytes(1).unpack('C')[0] == 1
52
+ end
53
+
54
+ def read_double
55
+ read_bytes(8).unpack('q<')[0]
56
+ end
57
+
58
+ def read_int32
59
+ read_bytes(4).unpack('i<')[0]
60
+ end
61
+
62
+ def read_int64
63
+ read_bytes(8).unpack('q<')[0]
64
+ end
65
+
66
+ def read_bytes(size)
67
+ raise TableStoreClientError.new("Read bytes encountered EOF.") if @buffer.length - @cur_pos < size
68
+ tmp_pos = @cur_pos
69
+ @cur_pos += size
70
+ @buffer[tmp_pos, size]
71
+ end
72
+
73
+ def read_utf_string(size)
74
+ raise TableStoreClientError.new("Read bytes encountered EOF.") if @buffer.length - @cur_pos < size
75
+ utf_str = @buffer[@cur_pos, size]
76
+ @cur_pos += size
77
+ utf_str.encode('utf-8') if utf_str.is_a?(String)
78
+ utf_str
79
+ end
80
+
81
+ def last_tag
82
+ @last_tag
83
+ end
84
+
85
+ def cur_pos
86
+ @cur_pos
87
+ end
88
+
89
+ def buffer
90
+ @buffer
91
+ end
92
+ end
@@ -0,0 +1,59 @@
1
+ require 'tablestore/error'
2
+
3
+ class PlainBufferOutputStream
4
+ def initialize(capacity)
5
+ @buffer = []
6
+ @capacity = capacity
7
+ end
8
+
9
+ def is_full?
10
+ @capacity <= @buffer.length
11
+ end
12
+
13
+ def count
14
+ @buffer.length
15
+ end
16
+
17
+ def remain
18
+ @capacity - count
19
+ end
20
+
21
+ def clear
22
+ @buffer.clear
23
+ end
24
+
25
+ def write_raw_byte(value)
26
+ raise TableStoreClientError.new("The buffer is full") if is_full?
27
+ @buffer << [value].pack("C*")
28
+ end
29
+
30
+ def write_raw_little_endian32(value)
31
+ write_bytes([value].pack("i"))
32
+ end
33
+
34
+ def write_raw_little_endian64(value)
35
+ write_bytes([value].pack("q"))
36
+ end
37
+
38
+ def write_double(value)
39
+ write_bytes([value].pack("d"))
40
+ end
41
+
42
+ def write_boolean(value)
43
+ bool_value = value ? 1 : 0
44
+ write_bytes([bool_value].pack("C"))
45
+ end
46
+
47
+ def write_bytes(value)
48
+ raise TableStoreClientError.new("The buffer is full.") if @buffer.length + value.length > @capacity
49
+ bytes = ''
50
+ value.to_s.each_byte do |b|
51
+ bytes += [b].pack("C*")
52
+ end
53
+ @buffer << bytes
54
+ end
55
+
56
+ def get_buffer
57
+ @buffer
58
+ end
59
+ end
@@ -0,0 +1,161 @@
1
+ require 'base64'
2
+
3
+ class OTSProtocol
4
+ $api_version = '2015-12-31'
5
+ $user_agent = 'table-store-ruby'
6
+
7
+ encoder_class = OTSProtoBufferEncoder.new
8
+ decoder_class = OTSProtoBufferDecoder.new
9
+
10
+ $api_list = [
11
+ 'CreateTable',
12
+ 'ListTable',
13
+ 'DeleteTable',
14
+ 'DescribeTable',
15
+ 'UpdateTable',
16
+ 'GetRow',
17
+ 'PutRow',
18
+ 'UpdateRow',
19
+ 'DeleteRow',
20
+ 'BatchGetRow',
21
+ 'BatchWriteRow',
22
+ 'GetRange'
23
+ ]
24
+
25
+ def initialize(user_id, user_key, sts_token, instance_name, encoding, logger)
26
+ @user_id = user_id
27
+ @user_key = user_key
28
+ @sts_token = sts_token
29
+ @instance_name = instance_name
30
+ @encoding = encoding
31
+ @encoder = encoder_class(encoding)
32
+ @decoder = decoder_class(encoding)
33
+ @logger = logger
34
+ end
35
+
36
+ def make_headers_string(headers)
37
+ headers.map{|k,v| "#{k.downcase}:#{v.strip}" if k.include?('x-ots-') and k != 'x-ots-signature'}.sort.join('\n')
38
+ end
39
+
40
+ def call_signature_method(signature_string)
41
+ salt = Digest::SHA1.digest(signature_string)
42
+ Base64.encode64(HMAC::SHA1.digest(UserSecret, salt)).strip
43
+ end
44
+
45
+ def make_request_signature(query, headers)
46
+ signature_string = query + '\n' + 'POST' + '\n\n'
47
+
48
+ headers_string = make_headers_string(headers)
49
+ signature_string += headers_string + '\n'
50
+ call_signature_method(signature_string)
51
+ end
52
+
53
+ def make_headers(body, query)
54
+ md5 = Base64.encode64(Digest::MD5.new.digest(body)).gsub(/\n/, '')
55
+ date = Time.now.strftime('%Y-%m-%dT%H:%M:%S.000Z')
56
+
57
+ headers = {
58
+ 'x-ots-date': date,
59
+ 'x-ots-apiversion': $api_version,
60
+ 'x-ots-accesskeyid': @user_id,
61
+ 'x-ots-instancename': @instance_name,
62
+ 'x-ots-contentmd5': md5,
63
+ }
64
+
65
+ headers['x-ots-ststoken'] = @sts_token if @sts_token.present?
66
+
67
+ signature = make_request_signature(query, headers)
68
+ headers['x-ots-signature'] = signature
69
+ headers['User-Agent'] = $user_agent
70
+ headers
71
+ end
72
+
73
+ def make_response_signature(query, headers)
74
+ uri = query
75
+ headers_string = make_headers_string(headers)
76
+
77
+ signature_string = headers_string + '\n' + uri
78
+ signature = call_signature_method(signature_string)
79
+ signature
80
+ end
81
+
82
+ def check_headers(headers, body, status=nil)
83
+ # check the response headers and process response body if needed.
84
+
85
+ header_names = [
86
+ 'x-ots-contentmd5',
87
+ 'x-ots-requestid',
88
+ 'x-ots-date',
89
+ 'x-ots-contenttype',
90
+ ]
91
+
92
+ if status >= 200 and status < 300
93
+ header_names.each do |name|
94
+ raise TableStoreClientError.new("#{name} is missing in response header.") unless headers.include?name
95
+
96
+ if headers.include?'x-ots-contentmd5'
97
+ md5 = Base64.encode64(Digest::MD5.new.digest(body)).gsub(/\n/, '')
98
+ end
99
+ raise TableStoreClientError.new('MD5 mismatch in response.') if md5 != headers['x-ots-contentmd5']
100
+ end
101
+ end
102
+ end
103
+
104
+ def check_authorization(query, headers, status=nil)
105
+ auth = headers.get('authorization')
106
+ if auth.nil?
107
+ if status >= 200 and status < 300
108
+ raise TableStoreClientError.new('"Authorization" is missing in response header.')
109
+ else
110
+ return
111
+ end
112
+ end
113
+ # 1, check authorization
114
+ unless auth.include?('OTS ')
115
+ raise TableStoreClientError.new('Invalid Authorization in response.')
116
+ end
117
+ # 2, check accessid
118
+ access_id, signature = auth[4..-1].split(':')
119
+ if access_id != self.user_id
120
+ raise TableStoreClientError.new('Invalid accesskeyid in response.')
121
+ end
122
+ # 3, check signature
123
+ # decode the byte type
124
+ if signature != make_response_signature(query, headers)
125
+ raise TableStoreClientError.new('Invalid signature in response.')
126
+ end
127
+ end
128
+
129
+ def make_request(api_name)
130
+ raise TableStoreClientError("API #{api_name} is not supported.") if $api_list.exclude?api_name
131
+ body = encoder.encode_request(api_name, *args)
132
+ query = '/' + api_name
133
+ headers = make_headers(body, query)
134
+ return query, headers, body
135
+ end
136
+
137
+ def get_request_id_string(headers)
138
+ request_id = headers.get('x-ots-requestid')
139
+ request_id = "" if request_id.nil?
140
+ request_id
141
+ end
142
+
143
+ def parse_response(api_name, status, headers, body)
144
+ raise TableStoreClientError.new("API #{api_name} is not supported.") unless api_list.include?(api_name)
145
+ begin
146
+ hash, proto = decoder.decode_response(api_name, body)
147
+ rescue => e
148
+ request_id = get_request_id_string(headers)
149
+ error_message = "Response format is invalid, #{e}, RequestID: #{request_id}, " \
150
+ "HTTP status: #{status}, Body: #{body}."
151
+ self.logger.error(error_message)
152
+ raise TableStoreClientError.new(error_message, status)
153
+ end
154
+ hash
155
+ end
156
+
157
+ # def handle_error(api_name, query, status, reason, headers, body)
158
+ #
159
+ # end
160
+
161
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tablestore-ruby-sdk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - seveninches
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-01-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: protobuf
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.8'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: digest-crc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: os
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ description: A simple tablestore gem
70
+ email: lijinghao333@aliyun.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - lib/consts.rb
76
+ - lib/protobuf/ots.proto
77
+ - lib/protobuf/ots_filiter.proto
78
+ - lib/protobuf/ots_filiter_pb.rb
79
+ - lib/protobuf/ots_pb.rb
80
+ - lib/tablestore-ruby-sdk.rb
81
+ - lib/tablestore/connection.rb
82
+ - lib/tablestore/crc8_auto.rb
83
+ - lib/tablestore/error.rb
84
+ - lib/tablestore/main.rb
85
+ - lib/tablestore/metadata.rb
86
+ - lib/tablestore/ots.rb
87
+ - lib/tablestore/plain_buffer_coded_input_stream.rb
88
+ - lib/tablestore/plain_buffer_coded_output_stream.rb
89
+ - lib/tablestore/plain_buffer_crc8.rb
90
+ - lib/tablestore/plain_buffer_input_stream.rb
91
+ - lib/tablestore/plain_buffer_output_stream.rb
92
+ - lib/tablestore/protocol.rb
93
+ homepage: http://rubygems.org/gems/tablestore-ruby-sdk
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.6.10
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: tablestore
117
+ test_files: []