aliyunoss 0.1.1

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