aliyunoss 0.1.1

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.
@@ -0,0 +1,66 @@
1
+ module Net
2
+
3
+ class HTTPResponse
4
+
5
+ def raise_if_not(status)
6
+ raise message unless status === self
7
+ end
8
+
9
+ def to_buckets
10
+ raise message unless Net::HTTPOK === self
11
+ nodes = Nokogiri::XML(self.body).xpath('//Bucket') rescue []
12
+ nodes.map do |node|
13
+ bucket = Aliyun::Oss::Bucket.new
14
+ node.elements.each {|e| bucket.send("#{e.name.underscore}=".to_sym, e.content)}
15
+ bucket
16
+ end
17
+ end
18
+
19
+ def to_objects
20
+ raise message unless Net::HTTPOK === self
21
+ nodes = Nokogiri::XML(self.body).xpath('//Contents') rescue []
22
+ nodes.map do |node|
23
+ hash = Hash.new
24
+ node.elements.each {|e| hash[e.name.underscore] = e.content unless e.name == 'Owner' }
25
+ hash
26
+ end
27
+ end
28
+
29
+ def to_logging_status
30
+ raise message unless Net::HTTPOK === self
31
+ node = Nokogiri::XML(self.body).xpath('//LoggingEnabled') rescue []
32
+ hash = Hash.new
33
+ node[0].elements.each {|e| hash[e.name.underscore] = e.content }
34
+ hash
35
+ end
36
+
37
+ def to_website_status
38
+ raise message unless Net::HTTPOK === self
39
+ xml = Nokogiri::XML(self.body)
40
+ {'index_page' => xml.xpath('//Suffix')[0].content, 'error_page' => xml.xpath('//Key')[0].content } rescue {}
41
+ end
42
+
43
+ def to_acl_status
44
+ raise message unless Net::HTTPOK === self
45
+ Nokogiri::XML(self.body).xpath('//Grant')[0].content
46
+ end
47
+
48
+ def to_multipart_id
49
+ raise message unless Net::HTTPOK === self
50
+ Nokogiri::XML(body).xpath('//UploadId').first.content
51
+ end
52
+
53
+ def to_mutlipart_task
54
+ raise message unless Net::HTTPOK === self
55
+ tasks = Array.new
56
+ nodes = Nokogiri::XML(response.body).xpath('//Upload')
57
+ nodes.each do |node|
58
+ path = '/' + node.xpath('Key').first.content
59
+ id = node.xpath('UploadId').first.content
60
+ tasks << {'path'=> path, 'upload_id' => id}
61
+ end
62
+ tasks
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,143 @@
1
+ # coding: utf-8
2
+ require 'base64'
3
+ require 'openssl'
4
+
5
+ module Aliyun
6
+ module Oss
7
+
8
+ class OssRequest
9
+
10
+ include ConfigHelper
11
+ attr_accessor :bucket, :path, :body, :queris
12
+
13
+ def initialize(bucket, path, queries = {}, headers = {})
14
+ @bucket = bucket
15
+ @path = path
16
+ @queries = queries
17
+ @headers = {"Content-Type" => "", "Content-MD5" => "", "Date" => Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')}.merge(headers)
18
+ end
19
+
20
+ def get_uri
21
+ if @bucket
22
+ uri = URI("http://#{bucket.name}.#{bucket.location}.#{host}")
23
+ else
24
+ uri = URI("http://oss.#{host}")
25
+ end
26
+ uri.path = @path
27
+ uri.query = @queries.to_query_string if @queries.count > 0
28
+ uri
29
+ end
30
+
31
+ def self.add_operation(verb)
32
+ define_method(verb) do
33
+ uri = get_uri
34
+
35
+ request = Net::HTTP.send(:const_get, verb.to_s.capitalize).new(uri)
36
+
37
+ @headers.each_pair {|k,v| request[k] = v}
38
+
39
+ if @body
40
+ request.body = @body
41
+ digest = OpenSSL::Digest::MD5.digest(@body)
42
+ request['Content-MD5'] = Base64.encode64(digest).strip
43
+ request['Content-Length'] = @body.bytesize
44
+ end
45
+
46
+ request['Authorization'] = 'OSS ' + access_key_id + ':' +
47
+ signature(request)
48
+
49
+ logger.info(verb.to_s.upcase + ' ' + uri.to_s + ' ' + request.to_hash.to_s)
50
+
51
+ response = nil
52
+ Net::HTTP.start(uri.host, uri.port) do |http|
53
+ response = http.request(request)
54
+ logger.info(response.code.to_s + ' ' + response.message)
55
+ logger.debug(response.body)
56
+ end
57
+ response
58
+ end
59
+ end
60
+
61
+ add_operation :get
62
+ add_operation :put
63
+ add_operation :delete
64
+ add_operation :head
65
+ add_operation :post
66
+
67
+ def url_for_sharing(expires)
68
+ raise "not implemented"
69
+ end
70
+
71
+ def [](key)
72
+ @headers[key]
73
+ end
74
+
75
+ def []=(key, value)
76
+ @headers[key] = value
77
+ end
78
+
79
+ private
80
+ def signature(req)
81
+ verb = req.class.to_s.gsub(/Net::HTTP::/, '').upcase
82
+ data = verb + "\n" + req["Content-MD5"] + "\n" +
83
+ req["Content-Type"] + "\n" + req["Date"] + "\n" +
84
+ canonicalized_oss_headers(req) +
85
+ canonicalized_resource()
86
+
87
+ digest = OpenSSL::Digest.new('sha1')
88
+ hmac = OpenSSL::HMAC.digest(digest, access_key_secret, data)
89
+ Base64.encode64(hmac).strip
90
+ end
91
+
92
+ # oss api 20140828.pdf - 4.2
93
+ # 1) 将所有以“x-oss-”为前缀的 HTTP 请求头的名字转换成小写字母。如 ’X-OSS-Meta-Name: TaoBao’
94
+ # 转换成 ’x-oss-meta-name: TaoBao’ 。
95
+ # 2) 将上一步得到的所有 HTTP 请求头按照字典序进行升序排列。
96
+ # 3) 如果有相同名字的请求头,则根据标准 RFC 2616, 4.2 章进行合并(两个值之间只用逗号分隔)。
97
+ # 如有两个名为’x-oss-meta-name’的请求头,对应的值分别为’TaoBao’和’Alipay’,则合并后
98
+ # 为: ’x-oss-meta-name:TaoBao,Alipay’ 。
99
+ # 4) 删除请求头和内容之间分隔符两端出现的任何空格。
100
+ # 如 ’x-oss-meta-name: TaoBao,Alipay’ 转换成: ’x-oss-meta-name:TaoBao,Alipay’ 。
101
+ # 5) 将所有的头和内容用 ’\n’ 分隔符分隔拼成最后的 CanonicalizedOSSHeader 。
102
+ def canonicalized_oss_headers(req)
103
+ hash = Hash.new
104
+ req.each_header do |header|
105
+ header = header.downcase
106
+ next unless header.start_with?('x-oss-')
107
+ if hash.has_key?(header)
108
+ hash[header] = hash[header] + "," + req[header].strip
109
+ else
110
+ hash[header] = req[header].strip
111
+ end
112
+ end
113
+
114
+ return "" if hash.count == 0
115
+
116
+ array = Array.new
117
+ hash.each_pair {|k,v| array << k + ":" + v }
118
+ array.sort.join("\n") << "\n"
119
+ end
120
+
121
+ # oss api 20140828.pdf - 4.2
122
+ # 1) 将 CanonicalizedResource 置成空字符串( “” );
123
+ # 2) 放入要访问的 OSS 资源:“ /BucketName/ObjectName ”(无 ObjectName 则不填)
124
+ # 3) 如果请求的资源包括子资源 (sub-resource) ,那么将所有的子资源按照字典序,从小到大排列并
125
+ # 以 ’&’ 为分隔符生成子资源字符串。在 CanonicalizedResource 字符串尾添加“?”和子资源字
126
+ # 符串。此时的 CanonicalizedResource 例子如: /BucketName/ObjectName?acl &uploadId=UploadId
127
+ # 4) 如果用户请求在查询字符串 (query string) 中指定了要重写 (override) 返回请求的 header,那么将这
128
+ # 些查询字符串及其请求值按照字典序,从小到大排列,以 ’&’ 为分隔符,按参数的字典序添加到
129
+ # CanonicalizedResource 中。此时的 CanonicalizedResource 例子:
130
+ # /BucketName/ObjectName?acl&response-content-type=ContentType & uploadId =UploadId
131
+ def canonicalized_resource()
132
+ return @path unless @bucket
133
+ return "/#{@bucket.name}#{@path}" if @queries.count == 0
134
+
135
+ array = Array.new
136
+ @queries.each_pair {|k,v| array << (if v then k+"="+v else k end)}
137
+ "/#{@bucket.name}#{@path}?#{array.sort.join('&')}"
138
+ end
139
+
140
+ end
141
+
142
+ end
143
+ end
@@ -0,0 +1,5 @@
1
+ module Aliyun
2
+ module Oss
3
+ VERSION = "0.1.1"
4
+ end
5
+ end
data/lib/aliyunoss.rb ADDED
@@ -0,0 +1,12 @@
1
+ # dependency
2
+ require 'nokogiri'
3
+ require 'net/http'
4
+ require 'logger'
5
+
6
+ require 'aliyunoss/helper'
7
+ require 'aliyunoss/config'
8
+ require 'aliyunoss/extension'
9
+ require 'aliyunoss/http_response_extension'
10
+ require 'aliyunoss/oss_request'
11
+ require 'aliyunoss/api'
12
+ require 'aliyunoss/bucket'
@@ -0,0 +1,2 @@
1
+ access_key_id: "access key _id from aliyun"
2
+ access_key_secret: "access key secret from aliyun"
@@ -0,0 +1,123 @@
1
+ require 'rspec'
2
+ require 'aliyunoss'
3
+
4
+ describe Aliyun::Oss::API do
5
+
6
+ before :all do
7
+ Aliyun::Oss.configure_with('spec/aliyunoss/aliyun-config.yml')
8
+ # Aliyun::Oss.configure(:log_level=> 'debug')
9
+ bucket_name = 'aliyun-oss-gem-api-test'
10
+ response = Aliyun::Oss::API.put_bucket(bucket_name)
11
+ expect(response).to be_a(Net::HTTPOK)
12
+ end
13
+
14
+ before :each do
15
+ @api = Aliyun::Oss::API
16
+ @bucket = Aliyun::Oss::Bucket.new(name: 'aliyun-oss-gem-api-test', location: 'oss-cn-hangzhou')
17
+ end
18
+
19
+ it 'should get bucket list using GetService api' do
20
+ response = @api.list_bucket
21
+ expect(response).to be_a(Net::HTTPOK)
22
+ end
23
+
24
+ it 'should disable bucket logging' do
25
+ expect(@api.delete_logging(@bucket)).to be_a(Net::HTTPNoContent)
26
+ end
27
+
28
+ it 'should disable bucket website access' do
29
+ expect(@api.delete_website(@bucket)).to be_a(Net::HTTPNoContent)
30
+ end
31
+
32
+ it 'should list objects in bucket' do
33
+ expect(@api.list_object(@bucket)).to be_a(Net::HTTPOK)
34
+ end
35
+
36
+ it 'should get bucket acl' do
37
+ response = @api.get_bucket_acl(@bucket)
38
+ expect(response).to be_a(Net::HTTPOK)
39
+ xml = Nokogiri::XML(response.body).xpath('//Grant')
40
+ expect(xml.count).to be >= 1
41
+ end
42
+
43
+ it 'should get bucket location' do
44
+ response = @api.get_bucket_location(@bucket)
45
+ expect(response).to be_a(Net::HTTPOK)
46
+ node = Nokogiri::XML(response.body).xpath('//LocationConstraint')[0]
47
+ expect(node.content).to eq('oss-cn-hangzhou')
48
+ end
49
+
50
+ it 'should get bucket logging status' do
51
+ response = @api.get_bucket_logging(@bucket)
52
+ expect(response).to be_a(Net::HTTPOK)
53
+ expect(response.body).to include('BucketLoggingStatus')
54
+ end
55
+
56
+ it 'should get bucket logging status' do
57
+ response = @api.get_bucket_website(@bucket)
58
+ expect(response).to be_a(Net::HTTPNotFound)
59
+ end
60
+
61
+ it 'should correctly set bucket acl permission' do
62
+ expect(@api.set_bucket_acl(@bucket, 'public-read')).to be_a(Net::HTTPOK)
63
+ expect(@api.set_bucket_acl(@bucket, 'public-read-write')).to be_a(Net::HTTPOK)
64
+ expect(@api.set_bucket_acl(@bucket, 'private')).to be_a(Net::HTTPOK)
65
+ end
66
+
67
+ it 'should enable and disable bucket logging func' do
68
+ expect(@api.disable_bucket_logging(@bucket)).to be_a(Net::HTTPOK)
69
+ expect(@api.enable_bucket_logging(@bucket, @bucket.name, 'logtest-')).to be_a(Net::HTTPOK)
70
+ end
71
+
72
+ it 'should set bucket website access configuration' do
73
+ expect(@api.set_bucket_website(@bucket, 'index.html','error.html')).to be_a(Net::HTTPOK)
74
+ end
75
+
76
+ it 'should upload file' do
77
+ files = ['test-1.png','test-2.png','test-3.png'].map {|f| File.join(__dir__, f)}
78
+ files.each do |f|
79
+ data = IO.read(f)
80
+ response = @api.put_object(@bucket, "/" + f[/test-\d\.png/], data, 'Content-Type'=>'image/png')
81
+ expect(response).to be_a(Net::HTTPOK)
82
+ end
83
+ end
84
+
85
+ it 'should copy object' do
86
+ sources = ['/test-1.png','/test-2.png','/test-3.png']
87
+ sources.each do |source_path|
88
+ response = @api.copy_object(@bucket, source_path, @bucket, "/copy-" + source_path[1,source_path.length-1])
89
+ expect(response).to be_a(Net::HTTPOK)
90
+ end
91
+ end
92
+
93
+ it 'should get object meta data' do
94
+ expect(@api.head_object(@bucket, '/test-1.png')).to be_a(Net::HTTPOK)
95
+ end
96
+
97
+ it 'should get object from oss' do
98
+ response = @api.get_object(@bucket, '/copy-test-1.png')
99
+ file_name = File.join(__dir__, 'test-1.png')
100
+ expect(response['Content-Length']).to eq(File.size(file_name).to_s)
101
+ expect(response['Content-Type']).to eq('image/png')
102
+ end
103
+
104
+ it 'should delete object' do
105
+ sources = ['/test-1.png','/test-2.png','/test-3.png']
106
+ sources.each do |path|
107
+ expect(@api.delete_object(@bucket,path)).to be_a(Net::HTTPNoContent)
108
+ end
109
+ end
110
+
111
+ it 'should delete multiple objects' do
112
+ response = @api.delete_multiple_objects(@bucket, ['copy-test-2.png','copy-test-3.png', 'copy-test-1.png'])
113
+ puts response.body
114
+ expect(response).to be_a(Net::HTTPOK)
115
+ end
116
+
117
+ it 'should delete this bucket' do
118
+ response = @api.delete_bucket(@bucket)
119
+ expect(response).to be_a(Net::HTTPNoContent)
120
+ end
121
+
122
+ end
123
+
@@ -0,0 +1,109 @@
1
+ require 'rspec'
2
+ require 'aliyunoss'
3
+
4
+ describe Aliyun::Oss::Bucket do
5
+
6
+ before :all do
7
+ Aliyun::Oss.configure_with('spec/aliyunoss/aliyun-config.yml')
8
+ end
9
+
10
+ before :each do
11
+ @bucket_name = 'aliyun-oss-gem-api-test'
12
+ @location = 'oss-cn-hangzhou'
13
+ @bucket = Aliyun::Oss::Bucket.all.select {|b| b.name == @bucket_name} .first
14
+ end
15
+
16
+ it 'should create a bucket' do
17
+ bucket = Aliyun::Oss::Bucket.create(@bucket_name, @location)
18
+ expect(bucket).to_not be_nil
19
+ end
20
+
21
+ it 'should list all buckets' do
22
+ buckets = Aliyun::Oss::Bucket.all
23
+ selected = buckets.select {|b| b.name == @bucket_name}
24
+ expect(selected.size).to eq(1)
25
+ end
26
+
27
+ it 'should list files on server' do
28
+ expect(@bucket.list_files).to_not be_nil
29
+ end
30
+
31
+ it 'should upload data to server' do
32
+ files = ['test-1.png','test-2.png','test-3.png'].map {|f| File.join(__dir__, f)}
33
+ files.each do |f|
34
+ data = IO.read(f)
35
+ @bucket.upload(data, "/" + f[/test-\d\.png/], 'Content-Type'=>'image/png')
36
+ end
37
+ end
38
+
39
+ it 'should upload data to server in multipart way' do
40
+ path = '/multi-part-test.dat'
41
+ @bucket.multipart_upload_initiate(path)
42
+
43
+ 10.times do
44
+ @bucket.multipart_upload( Random.new.bytes(1024 * rand(100..300)) )
45
+ end
46
+
47
+ @bucket.multipart_upload_complete
48
+ end
49
+
50
+ it 'should copy data in multipart way' do
51
+ pending 'I get Forbidden using x-oss-copy-source-range'
52
+ source_path = '/multi-part-test.dat'
53
+ source_object = @bucket.list_files.select {|f| '/' + f['key'] == source_path} .first
54
+ source_size = source_object['size'].to_i
55
+
56
+ target_path = '/multi-part-copy.dat'
57
+ @bucket.multipart_upload_initiate(target_path)
58
+ @bucket.multipart_copy_from(@bucket, source_path, 1024*100, "bytes=0-#{1024*100-1}")
59
+ @bucket.multipart_upload_complete
60
+ end
61
+
62
+ it 'should download file from server' do
63
+ ['/test-1.png','/test-2.png','/test-3.png'].each do |path|
64
+ remote_data = @bucket.download(path)
65
+ local_data = IO.read(File.join(__dir__, path))
66
+ md5 = OpenSSL::Digest::MD5
67
+ expect(md5.digest(remote_data)).to eq(md5.digest(local_data))
68
+ end
69
+ end
70
+
71
+ it 'should delete file on server' do
72
+ ['/test-1.png','/test-2.png','/test-3.png', '/multi-part-test.dat', '/multi-part-copy.dat'].each do |path|
73
+ @bucket.delete(path)
74
+ end
75
+ end
76
+
77
+ it 'should get and modify logging status' do
78
+ @bucket.enable_logging('aliyun-oss-gem-api-test', 'access_log')
79
+ sleep(2)
80
+ expect(@bucket.logging_status['target_bucket']).to eq('aliyun-oss-gem-api-test')
81
+ expect(@bucket.logging_status['target_prefix']).to eq('access_log')
82
+ @bucket.disable_logging
83
+ end
84
+
85
+ it 'should get and modify website access status' do
86
+ @bucket.enable_website_access('index.html','error.html')
87
+ sleep(2)
88
+ expect(@bucket.website_access_status['index_page']).to eq('index.html')
89
+ expect(@bucket.website_access_status['error_page']).to eq('error.html')
90
+ @bucket.disable_website_access
91
+ end
92
+
93
+ it 'should get and set access control list' do
94
+ @bucket.set_acl('public-read')
95
+ sleep(2)
96
+ expect(@bucket.get_acl).to eq('public-read')
97
+ @bucket.set_acl('private')
98
+ end
99
+
100
+ it 'should delete specified bucket' do
101
+ @bucket.multipart_pending.each do |task|
102
+ @bucket.multipart_abort(task['path'], task['upload_id'])
103
+ end
104
+
105
+ @bucket.delete!
106
+ expect {Bucket.new(:name=> 'bucket_not_exist').delete!}.to raise_error
107
+ end
108
+
109
+ end
@@ -0,0 +1,47 @@
1
+ require 'rspec'
2
+ require 'aliyunoss'
3
+
4
+ describe 'Aliyun::Oss Configuration' do
5
+
6
+ before :each do
7
+ config = Aliyun::Oss.config
8
+ config[:log_level] = 'info'
9
+ config[:host] = 'aliyuncs.com'
10
+ config[:access_key_id] = nil
11
+ config[:access_key_secret] = nil
12
+ end
13
+
14
+ it 'should load default options' do
15
+ default_config = Aliyun::Oss.config
16
+ expect(default_config).to include(:log_level)
17
+ expect(default_config).to include(:host)
18
+ expect(default_config).to include(:access_key_id)
19
+ end
20
+
21
+ it 'should accept configuration from #configure' do
22
+ url = "http://bucket_name.region.aliyuncs.com"
23
+ access_key = "access_key_from_aliyun"
24
+ Aliyun::Oss.configure(:log_level => 'debug', :host => url, :access_key_id => access_key, :not_used_para => "not used")
25
+ config = Aliyun::Oss.config
26
+ expect(config.keys).not_to include(:not_used_para)
27
+ expect(config[:host]).to eq(url)
28
+ expect(config[:access_key_id]).to eq(access_key)
29
+ expect(config[:log_level]).to eq('debug')
30
+ end
31
+
32
+ it 'should load yaml config file if specified' do
33
+ Aliyun::Oss.configure_with('spec/aliyunoss/aliyun-config.yml.sample')
34
+ config = Aliyun::Oss.config
35
+ expect(config[:host]).to eq('bucket_name.region.aliyuncs.com')
36
+ expect(config[:access_key_id]).to eq('access key _id from aliyun')
37
+ end
38
+
39
+ it 'should load default configuration if incorrect yaml file specified' do
40
+ Aliyun::Oss.configure_with('spec/aliyunoss/incorrect-config.yml')
41
+ config = Aliyun::Oss.config
42
+ expect(config[:host]).not_to eq('aliyun-yaml.com')
43
+ expect(config[:access_key_id]).not_to eq('1234567890')
44
+ end
45
+
46
+ it 'should load configuration from RAILS_ROOT/config/aliyun-oss.yml in Rails project'
47
+ end
@@ -0,0 +1,4 @@
1
+ this is incorrect yaml
2
+ format file
3
+ host: incorrect-yaml.com
4
+ access_key_id: "incorrect-1234567890"
@@ -0,0 +1,103 @@
1
+ require 'rspec'
2
+ require 'aliyunoss'
3
+
4
+ describe Aliyun::Oss::API do
5
+
6
+ before :all do
7
+ Aliyun::Oss.configure_with('spec/aliyunoss/aliyun-config.yml')
8
+ Aliyun::Oss.configure(:log_level=> 'debug')
9
+ bucket_name = 'aliyun-oss-gem-api-test'
10
+ response = Aliyun::Oss::API.put_bucket(bucket_name)
11
+ expect(response).to be_a(Net::HTTPOK)
12
+ end
13
+
14
+ before :each do
15
+ @api = Aliyun::Oss::API
16
+ @bucket = Aliyun::Oss::Bucket.new(name: 'aliyun-oss-gem-api-test', location: 'oss-cn-hangzhou')
17
+ end
18
+
19
+ it 'should upload data in multipart way' do
20
+ path = '/multi-part-test.dat'
21
+ response = @api.multipart_upload_initiate(@bucket, path)
22
+ expect(response).to be_a(Net::HTTPOK)
23
+
24
+ upload_id = Nokogiri::XML(response.body).xpath('//UploadId')[0].content
25
+ expect(upload_id).to_not be_nil
26
+
27
+ part_list = {}
28
+ (1..10).each do |no|
29
+ data = Random.new.bytes(1024 * rand(100..300))
30
+ response = @api.multipart_upload_part(@bucket, path,upload_id, data, no)
31
+ expect(response).to be_a(Net::HTTPOK)
32
+ expect(response['ETag']).to_not be_nil
33
+ expect(response['ETag']).to be_a(String)
34
+ part_list[no] = response['ETag']
35
+ end
36
+
37
+ response = @api.multipart_upload_finished_parts(@bucket, path, upload_id)
38
+ expect(response).to be_a(Net::HTTPOK)
39
+ expect(response.body.include?('ListPartsResult')).to be true
40
+
41
+ response = @api.multipart_upload_complete(@bucket, path, upload_id, part_list)
42
+ expect(response).to be_a(Net::HTTPOK)
43
+ end
44
+
45
+ it 'should aboart uploading' do
46
+ path = '/multi-part-test-aborted.dat'
47
+ response = @api.multipart_upload_initiate(@bucket, path)
48
+ expect(response).to be_a(Net::HTTPOK)
49
+
50
+ upload_id = Nokogiri::XML(response.body).xpath('//UploadId')[0].content
51
+ expect(upload_id).to_not be_nil
52
+
53
+ data = Random.new.bytes(1024 * rand(100..300))
54
+
55
+ response = @api.multipart_upload_part(@bucket, path, upload_id, data, 1)
56
+ expect(response).to be_a(Net::HTTPOK)
57
+
58
+ response = @api.multipart_upload_abort(@bucket, path, upload_id)
59
+ expect(response).to be_a(Net::HTTPNoContent)
60
+ end
61
+
62
+ it 'should copy object from bucket in multipart way' do
63
+ path = '/copy-multi-part-test.dat'
64
+ response = @api.multipart_upload_initiate(@bucket, path)
65
+ expect(response).to be_a(Net::HTTPOK)
66
+
67
+ upload_id = Nokogiri::XML(response.body).xpath('//UploadId')[0].content
68
+ expect(upload_id).to_not be_nil
69
+
70
+ data = Random.new.bytes(1024 * rand(100..300))
71
+
72
+ response = @api.multipart_upload_from_copy(upload_id, @bucket, '/multi-part-test.dat',
73
+ @bucket, path, 1, 1024*500)
74
+ expect(response).to be_a(Net::HTTPOK)
75
+
76
+ response = @api.multipart_upload_abort(@bucket, path, upload_id)
77
+ expect(response).to be_a(Net::HTTPNoContent)
78
+ end
79
+
80
+ it 'should delete uploaded file' do
81
+ expect(@api.delete_object(@bucket,'/multi-part-test.dat')).to be_a(Net::HTTPNoContent)
82
+ end
83
+
84
+ it 'should list unfinished multipart upload task' do
85
+ response = @api.multipart_upload_unfinished_task(@bucket)
86
+ expect(response).to be_a(Net::HTTPOK)
87
+
88
+ # cancel all unfinished task
89
+ nodes = Nokogiri::XML(response.body).xpath('//Upload')
90
+ nodes.each do |node|
91
+ path = '/' + node.xpath('Key').first.content
92
+ id = node.xpath('UploadId').first.content
93
+ response = @api.multipart_upload_abort(@bucket, path, id)
94
+ expect(response).to be_a(Net::HTTPNoContent)
95
+ end
96
+ end
97
+
98
+ it 'should delete this bucket' do
99
+ response = Aliyun::Oss::API.delete_bucket(@bucket)
100
+ expect(response).to be_a(Net::HTTPNoContent)
101
+ end
102
+
103
+ end
@@ -0,0 +1,51 @@
1
+ # coding: utf-8
2
+ require 'rspec'
3
+ require 'aliyunoss'
4
+
5
+ describe Aliyun::Oss::OssRequest do
6
+
7
+ it 'should correctly calculate CanonicalizedOssHeader' do
8
+ Aliyun::Oss.configure(:access_key_id => '44CF9590006BF252F707',
9
+ :access_key_secret => 'OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV')
10
+ req = Net::HTTP::Get.new(URI("http://" + Aliyun::Oss.config[:host] + "/nelson"))
11
+ req["X-OSS-Meta-Author"] = "foo@bar.com"
12
+ req["X-OSS-Magic"] = "abracadabra"
13
+ req["Date"] = "Thu, 17 Nov 2005 18:49:58 GMT"
14
+ req["Content-Type"] = "text/html"
15
+ req["Content-MD5"] = "ODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM="
16
+ result = Aliyun::Oss::OssRequest.new(nil, '/').
17
+ send(:canonicalized_oss_headers, req)
18
+ expect(result).to eq("x-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n")
19
+ end
20
+
21
+ it 'should correctly calculate CanonicalResource' do
22
+ bucket = Aliyun::Oss::Bucket.new(:name=>'BucketName',
23
+ :location=> 'oss-cn-hangzhou')
24
+ path = '/ObjectName'
25
+ queries = {"acl"=>nil, "uploadId"=>"UploadId",
26
+ "response-content-type"=>"ContentType" }
27
+ result = Aliyun::Oss::OssRequest.new(bucket, path, queries).
28
+ send(:canonicalized_resource)
29
+ expect(result).to eq("/BucketName/ObjectName?acl&response-content-type=ContentType&uploadId=UploadId")
30
+
31
+ result = Aliyun::Oss::OssRequest.new(bucket, path).
32
+ send(:canonicalized_resource)
33
+ expect(result).to eq("/BucketName/ObjectName")
34
+ end
35
+
36
+ it 'should correctly calculate signature in Authorization header' do
37
+ Aliyun::Oss.configure(:access_key_id => '44CF9590006BF252F707',
38
+ :access_key_secret => 'OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV')
39
+ bucket = Aliyun::Oss::Bucket.new(name: 'oss-example', location: 'oss-cn-hangzhou')
40
+ oss_req = Aliyun::Oss::OssRequest.new(bucket, '/nelson')
41
+ param = Net::HTTP::Put.new(oss_req.get_uri)
42
+ param["X-OSS-Meta-Author"] = "foo@bar.com"
43
+ param["X-OSS-Magic"] = "abracadabra"
44
+ param["Date"] = "Thu, 17 Nov 2005 18:49:58 GMT"
45
+ param["Content-Type"] = "text/html"
46
+ param["Content-MD5"] = "ODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM="
47
+ result = oss_req.send(:signature, param)
48
+ expect(result).to eq("26NBxoKdsyly4EDv6inkoDft/yA=")
49
+ end
50
+
51
+ end
Binary file
Binary file
Binary file