aliyun-sdk 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/examples/aliyun/oss/resumable_download.rb +3 -1
- data/examples/aliyun/oss/resumable_upload.rb +4 -1
- data/lib/aliyun/oss/bucket.rb +6 -0
- data/lib/aliyun/oss/http.rb +7 -7
- data/lib/aliyun/oss/object.rb +1 -1
- data/lib/aliyun/oss/protocol.rb +51 -20
- data/lib/aliyun/oss/util.rb +3 -3
- data/lib/aliyun/version.rb +1 -1
- data/spec/aliyun/oss/client/bucket_spec.rb +55 -0
- data/spec/aliyun/oss/client/resumable_upload_spec.rb +27 -31
- data/spec/aliyun/oss/util_spec.rb +4 -4
- data/tests/test_content_type.rb +10 -10
- data/tests/test_custom_headers.rb +75 -0
- data/tests/test_object_acl.rb +54 -0
- metadata +5 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92abcf259fe7eaea3a58e48e8e9fa46b6e7a842e
|
4
|
+
data.tar.gz: c1c3c72bd651bc19bf42b1a325bf55003852487d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4221cfa8663737bed084077793f6acaed03fcd5912a3fd1741f5b71435c9ccc1b25071123c59801fc5613c64e38bd168206885d4b5221f2269cbb549e26c6dc
|
7
|
+
data.tar.gz: 86123f41ba9d877d6443df644e16053235fe473fb6d7ede26f9a64d9f50e44b27d4db2ba253c3959a42931c5dc54b0181f8075e91765f127074afe036a509dbd
|
data/CHANGELOG.md
CHANGED
@@ -25,10 +25,12 @@ end
|
|
25
25
|
|
26
26
|
demo "Resumable download" do
|
27
27
|
# 下载一个100M的文件
|
28
|
+
cpt_file = '/tmp/y.cpt'
|
29
|
+
File.delete(cpt_file) if File.exist?(cpt_file)
|
28
30
|
start = Time.now
|
29
31
|
puts "Start download: resumable => /tmp/y"
|
30
32
|
bucket.resumable_download(
|
31
|
-
'resumable', '/tmp/y', :cpt_file =>
|
33
|
+
'resumable', '/tmp/y', :cpt_file => cpt_file) do |progress|
|
32
34
|
puts "Progress: #{(progress * 100).round(2)} %"
|
33
35
|
end
|
34
36
|
puts "Download complete. Cost: #{Time.now - start} seconds."
|
@@ -30,11 +30,14 @@ demo "Resumable upload" do
|
|
30
30
|
(1..1024*1024).each{ |i| f.puts i.to_s.rjust(99, '0') }
|
31
31
|
end
|
32
32
|
|
33
|
+
cpt_file = '/tmp/x.cpt'
|
34
|
+
File.delete(cpt_file) if File.exist?(cpt_file)
|
35
|
+
|
33
36
|
# 上传一个100M的文件
|
34
37
|
start = Time.now
|
35
38
|
puts "Start upload: /tmp/x => resumable"
|
36
39
|
bucket.resumable_upload(
|
37
|
-
'resumable', '/tmp/x', :cpt_file =>
|
40
|
+
'resumable', '/tmp/x', :cpt_file => cpt_file) do |progress|
|
38
41
|
puts "Progress: #{(progress * 100).round(2)} %"
|
39
42
|
end
|
40
43
|
puts "Upload complete. Cost: #{Time.now - start} seconds."
|
data/lib/aliyun/oss/bucket.rb
CHANGED
@@ -181,6 +181,8 @@ module Aliyun
|
|
181
181
|
# @option opts [Callback] :callback 指定操作成功后OSS的
|
182
182
|
# 上传回调,上传成功后OSS会向用户的应用服务器发一个HTTP POST请
|
183
183
|
# 求,`:callback`参数指定这个请求的相关参数
|
184
|
+
# @option opts [Hash] :headers 指定请求的HTTP Header,不区分大小
|
185
|
+
# 写。这里指定的值会覆盖通过`:content_type`和`:metas`设置的值。
|
184
186
|
# @yield [HTTP::StreamWriter] 如果调用的时候传递了block,则写入
|
185
187
|
# 到object的数据由block指定
|
186
188
|
# @example 流式上传数据
|
@@ -315,6 +317,8 @@ module Aliyun
|
|
315
317
|
# @option opts [Hash] :metas 设置object的meta,这是一些用户自定
|
316
318
|
# 义的属性,它们会和object一起存储,在{#get_object}的时候会
|
317
319
|
# 返回这些meta。属性的key不区分大小写。例如:{ 'year' => '2015' }
|
320
|
+
# @option opts [Hash] :headers 指定请求的HTTP Header,不区分大小
|
321
|
+
# 写。这里指定的值会覆盖通过`:content_type`和`:metas`设置的值。
|
318
322
|
# @example 流式上传数据
|
319
323
|
# pos = append_object('x', 0){ |stream| 100.times { |i| stream << i.to_s } }
|
320
324
|
# append_object('x', pos){ |stream| stream << get_data }
|
@@ -439,6 +443,8 @@ module Aliyun
|
|
439
443
|
# @option opts [Callback] :callback 指定文件上传成功后OSS的
|
440
444
|
# 上传回调,上传成功后OSS会向用户的应用服务器发一个HTTP POST请
|
441
445
|
# 求,`:callback`参数指定这个请求的相关参数
|
446
|
+
# @option opts [Hash] :headers 指定请求的HTTP Header,不区分大小
|
447
|
+
# 写。这里指定的值会覆盖通过`:content_type`和`:metas`设置的值。
|
442
448
|
# @yield [Float] 如果调用的时候传递了block,则会将上传进度交由
|
443
449
|
# block处理,进度值是一个0-1之间的小数
|
444
450
|
# @raise [CheckpointBrokenError] 如果cpt文件被损坏,则抛出此错误
|
data/lib/aliyun/oss/http.rb
CHANGED
@@ -207,16 +207,16 @@ module Aliyun
|
|
207
207
|
sub_res = resources[:sub_res]
|
208
208
|
|
209
209
|
headers = http_options[:headers] || {}
|
210
|
-
headers['
|
211
|
-
headers['
|
212
|
-
headers['
|
210
|
+
headers['user-agent'] = get_user_agent
|
211
|
+
headers['date'] = Time.now.httpdate
|
212
|
+
headers['content-type'] ||= DEFAULT_CONTENT_TYPE
|
213
213
|
headers[STS_HEADER] = @config.sts_token if @config.sts_token
|
214
214
|
|
215
215
|
if body = http_options[:body]
|
216
216
|
if body.respond_to?(:read)
|
217
|
-
headers['
|
217
|
+
headers['transfer-encoding'] = 'chunked'
|
218
218
|
else
|
219
|
-
headers['
|
219
|
+
headers['content-md5'] = Util.get_content_md5(body)
|
220
220
|
end
|
221
221
|
end
|
222
222
|
|
@@ -227,7 +227,7 @@ module Aliyun
|
|
227
227
|
|
228
228
|
if @config.access_key_id and @config.access_key_secret
|
229
229
|
sig = Util.get_signature(@config.access_key_secret, verb, headers, res)
|
230
|
-
headers['
|
230
|
+
headers['authorization'] = "OSS #{@config.access_key_id}:#{sig}"
|
231
231
|
end
|
232
232
|
|
233
233
|
logger.debug("Send HTTP request, verb: #{verb}, resources: " \
|
@@ -295,7 +295,7 @@ module RestClient
|
|
295
295
|
module Payload
|
296
296
|
class Base
|
297
297
|
def headers
|
298
|
-
({'
|
298
|
+
({'content-length' => size.to_s} if size) || {}
|
299
299
|
end
|
300
300
|
end
|
301
301
|
end
|
data/lib/aliyun/oss/object.rb
CHANGED
data/lib/aliyun/oss/protocol.rb
CHANGED
@@ -499,6 +499,8 @@ module Aliyun
|
|
499
499
|
# @param bucket_name [String] the bucket name
|
500
500
|
# @param object_name [String] the object name
|
501
501
|
# @param opts [Hash] Options
|
502
|
+
# @option opts [String] :acl specify the object's ACL. See
|
503
|
+
# {OSS::ACL}
|
502
504
|
# @option opts [String] :content_type the HTTP Content-Type
|
503
505
|
# for the file, if not specified client will try to determine
|
504
506
|
# the type itself and fall back to HTTP::DEFAULT_CONTENT_TYPE
|
@@ -508,6 +510,9 @@ module Aliyun
|
|
508
510
|
# with the object
|
509
511
|
# @option opts [Callback] :callback the HTTP callback performed
|
510
512
|
# by OSS after `put_object` succeeds
|
513
|
+
# @option opts [Hash] :headers custom HTTP headers, case
|
514
|
+
# insensitive. Headers specified here will overwrite `:metas`
|
515
|
+
# and `:content_type`
|
511
516
|
# @yield [HTTP::StreamWriter] a stream writer is
|
512
517
|
# yielded to the caller to which it can write chunks of data
|
513
518
|
# streamingly
|
@@ -518,14 +523,17 @@ module Aliyun
|
|
518
523
|
logger.debug("Begin put object, bucket: #{bucket_name}, object: "\
|
519
524
|
"#{object_name}, options: #{opts}")
|
520
525
|
|
521
|
-
headers = {'
|
526
|
+
headers = {'content-type' => opts[:content_type]}
|
527
|
+
headers['x-oss-object-acl'] = opts[:acl] if opts.key?(:acl)
|
528
|
+
to_lower_case(opts[:metas] || {})
|
529
|
+
.each { |k, v| headers["x-oss-meta-#{k.to_s}"] = v.to_s }
|
530
|
+
|
531
|
+
headers.merge!(to_lower_case(opts[:headers])) if opts.key?(:headers)
|
532
|
+
|
522
533
|
if opts.key?(:callback)
|
523
534
|
headers[CALLBACK_HEADER] = opts[:callback].serialize
|
524
535
|
end
|
525
536
|
|
526
|
-
(opts[:metas] || {})
|
527
|
-
.each { |k, v| headers["x-oss-meta-#{k.to_s}"] = v.to_s }
|
528
|
-
|
529
537
|
r = @http.put(
|
530
538
|
{:bucket => bucket_name, :object => object_name},
|
531
539
|
{:headers => headers, :body => HTTP::StreamPayload.new(&block)})
|
@@ -546,6 +554,8 @@ module Aliyun
|
|
546
554
|
# @param object_name [String] the object name
|
547
555
|
# @param position [Integer] the position to append
|
548
556
|
# @param opts [Hash] Options
|
557
|
+
# @option opts [String] :acl specify the object's ACL. See
|
558
|
+
# {OSS::ACL}
|
549
559
|
# @option opts [String] :content_type the HTTP Content-Type
|
550
560
|
# for the file, if not specified client will try to determine
|
551
561
|
# the type itself and fall back to HTTP::DEFAULT_CONTENT_TYPE
|
@@ -553,6 +563,9 @@ module Aliyun
|
|
553
563
|
# @option opts [Hash<Symbol, String>] :metas key-value pairs
|
554
564
|
# that serve as the object meta which will be stored together
|
555
565
|
# with the object
|
566
|
+
# @option opts [Hash] :headers custom HTTP headers, case
|
567
|
+
# insensitive. Headers specified here will overwrite `:metas`
|
568
|
+
# and `:content_type`
|
556
569
|
# @return [Integer] next position to append
|
557
570
|
# @yield [HTTP::StreamWriter] a stream writer is
|
558
571
|
# yielded to the caller to which it can write chunks of data
|
@@ -566,10 +579,13 @@ module Aliyun
|
|
566
579
|
"#{object_name}, position: #{position}, options: #{opts}")
|
567
580
|
|
568
581
|
sub_res = {'append' => nil, 'position' => position}
|
569
|
-
headers = {'
|
570
|
-
|
582
|
+
headers = {'content-type' => opts[:content_type]}
|
583
|
+
headers['x-oss-object-acl'] = opts[:acl] if opts.key?(:acl)
|
584
|
+
to_lower_case(opts[:metas] || {})
|
571
585
|
.each { |k, v| headers["x-oss-meta-#{k.to_s}"] = v.to_s }
|
572
586
|
|
587
|
+
headers.merge!(to_lower_case(opts[:headers])) if opts.key?(:headers)
|
588
|
+
|
573
589
|
r = @http.post(
|
574
590
|
{:bucket => bucket_name, :object => object_name, :sub_res => sub_res},
|
575
591
|
{:headers => headers, :body => HTTP::StreamPayload.new(&block)})
|
@@ -721,7 +737,7 @@ module Aliyun
|
|
721
737
|
rewrites = opts[:rewrite]
|
722
738
|
|
723
739
|
headers = {}
|
724
|
-
headers['
|
740
|
+
headers['range'] = get_bytes_range(range) if range
|
725
741
|
headers.merge!(get_conditions(conditions)) if conditions
|
726
742
|
|
727
743
|
sub_res = {}
|
@@ -758,7 +774,7 @@ module Aliyun
|
|
758
774
|
:etag => h[:etag],
|
759
775
|
:metas => metas,
|
760
776
|
:last_modified => wrap(h[:last_modified]) { |x| Time.parse(x) },
|
761
|
-
:
|
777
|
+
:headers => h)
|
762
778
|
|
763
779
|
logger.debug("Done get object")
|
764
780
|
|
@@ -801,7 +817,7 @@ module Aliyun
|
|
801
817
|
:etag => h[:etag],
|
802
818
|
:metas => metas,
|
803
819
|
:last_modified => wrap(h[:last_modified]) { |x| Time.parse(x) },
|
804
|
-
:
|
820
|
+
:headers => h)
|
805
821
|
|
806
822
|
logger.debug("Done get object meta")
|
807
823
|
|
@@ -840,7 +856,7 @@ module Aliyun
|
|
840
856
|
headers = {
|
841
857
|
'x-oss-copy-source' =>
|
842
858
|
@http.get_resource_path(bucket_name, src_object_name),
|
843
|
-
'
|
859
|
+
'content-type' => opts[:content_type]
|
844
860
|
}
|
845
861
|
(opts[:metas] || {})
|
846
862
|
.each { |k, v| headers["x-oss-meta-#{k.to_s}"] = v.to_s }
|
@@ -982,9 +998,9 @@ module Aliyun
|
|
982
998
|
"headers: #{headers.join(',')}")
|
983
999
|
|
984
1000
|
h = {
|
985
|
-
'
|
986
|
-
'
|
987
|
-
'
|
1001
|
+
'origin' => origin,
|
1002
|
+
'access-control-request-method' => method,
|
1003
|
+
'access-control-request-headers' => headers.join(',')
|
988
1004
|
}
|
989
1005
|
|
990
1006
|
r = @http.options(
|
@@ -1017,16 +1033,21 @@ module Aliyun
|
|
1017
1033
|
# @option opts [Hash<Symbol, String>] :metas key-value pairs
|
1018
1034
|
# that serve as the object meta which will be stored together
|
1019
1035
|
# with the object
|
1036
|
+
# @option opts [Hash] :headers custom HTTP headers, case
|
1037
|
+
# insensitive. Headers specified here will overwrite `:metas`
|
1038
|
+
# and `:content_type`
|
1020
1039
|
# @return [String] the upload id
|
1021
1040
|
def initiate_multipart_upload(bucket_name, object_name, opts = {})
|
1022
1041
|
logger.info("Begin initiate multipart upload, bucket: "\
|
1023
1042
|
"#{bucket_name}, object: #{object_name}, options: #{opts}")
|
1024
1043
|
|
1025
1044
|
sub_res = {'uploads' => nil}
|
1026
|
-
headers = {'
|
1027
|
-
(opts[:metas] || {})
|
1045
|
+
headers = {'content-type' => opts[:content_type]}
|
1046
|
+
to_lower_case(opts[:metas] || {})
|
1028
1047
|
.each { |k, v| headers["x-oss-meta-#{k.to_s}"] = v.to_s }
|
1029
1048
|
|
1049
|
+
headers.merge!(to_lower_case(opts[:headers])) if opts.key?(:headers)
|
1050
|
+
|
1030
1051
|
r = @http.post(
|
1031
1052
|
{:bucket => bucket_name, :object => object_name,
|
1032
1053
|
:sub_res => sub_res},
|
@@ -1092,7 +1113,7 @@ module Aliyun
|
|
1092
1113
|
'x-oss-copy-source' =>
|
1093
1114
|
@http.get_resource_path(bucket_name, source_object)
|
1094
1115
|
}
|
1095
|
-
headers['
|
1116
|
+
headers['range'] = get_bytes_range(range) if range
|
1096
1117
|
headers.merge!(get_copy_conditions(conditions)) if conditions
|
1097
1118
|
|
1098
1119
|
sub_res = {'partNumber' => part_no, 'uploadId' => txn_id}
|
@@ -1392,14 +1413,14 @@ module Aliyun
|
|
1392
1413
|
# @return [Hash] conditions for HTTP headers
|
1393
1414
|
def get_conditions(conditions)
|
1394
1415
|
{
|
1395
|
-
:if_modified_since => '
|
1396
|
-
:if_unmodified_since => '
|
1416
|
+
:if_modified_since => 'if-modified-since',
|
1417
|
+
:if_unmodified_since => 'if-unmodified-since',
|
1397
1418
|
}.reduce({}) { |h, (k, v)|
|
1398
1419
|
conditions.key?(k)? h.merge(v => conditions[k].httpdate) : h
|
1399
1420
|
}.merge(
|
1400
1421
|
{
|
1401
|
-
:if_match_etag => '
|
1402
|
-
:if_unmatch_etag => '
|
1422
|
+
:if_match_etag => 'if-match',
|
1423
|
+
:if_unmatch_etag => 'if-none-match'
|
1403
1424
|
}.reduce({}) { |h, (k, v)|
|
1404
1425
|
conditions.key?(k)? h.merge(v => conditions[k]) : h
|
1405
1426
|
}
|
@@ -1445,6 +1466,16 @@ module Aliyun
|
|
1445
1466
|
kv.each { |k, v| hash[k] = v.call(hash[k]) if hash.key?(k) }
|
1446
1467
|
end
|
1447
1468
|
|
1469
|
+
# Convert hash keys to lower case Non-Recursively
|
1470
|
+
# @param hash [Hash] the hash to be converted
|
1471
|
+
# @return [Hash] hash with lower case keys
|
1472
|
+
def to_lower_case(hash)
|
1473
|
+
hash.reduce({}) do |result, (k, v)|
|
1474
|
+
result[k.to_s.downcase] = v
|
1475
|
+
result
|
1476
|
+
end
|
1477
|
+
end
|
1478
|
+
|
1448
1479
|
end # Protocol
|
1449
1480
|
end # OSS
|
1450
1481
|
end # Aliyun
|
data/lib/aliyun/oss/util.rb
CHANGED
@@ -24,9 +24,9 @@ module Aliyun
|
|
24
24
|
def get_signature(key, verb, headers, resources)
|
25
25
|
logger.debug("Sign, headers: #{headers}, resources: #{resources}")
|
26
26
|
|
27
|
-
content_md5 = headers['
|
28
|
-
content_type = headers['
|
29
|
-
date = headers['
|
27
|
+
content_md5 = headers['content-md5'] || ""
|
28
|
+
content_type = headers['content-type'] || ""
|
29
|
+
date = headers['date']
|
30
30
|
|
31
31
|
cano_headers = headers.select { |k, v| k.start_with?(HEADER_PREFIX) }
|
32
32
|
.map { |k, v| [k.downcase.strip, v.strip] }
|
data/lib/aliyun/version.rb
CHANGED
@@ -239,6 +239,17 @@ module Aliyun
|
|
239
239
|
.with(:body => content, :query => {})
|
240
240
|
end
|
241
241
|
|
242
|
+
it "should put object with acl" do
|
243
|
+
key = 'ruby'
|
244
|
+
stub_request(:put, object_url(key))
|
245
|
+
|
246
|
+
@bucket.put_object(key, :acl => ACL::PUBLIC_READ)
|
247
|
+
|
248
|
+
expect(WebMock)
|
249
|
+
.to have_requested(:put, object_url(key))
|
250
|
+
.with(:headers => {'X-Oss-Object-Acl' => ACL::PUBLIC_READ})
|
251
|
+
end
|
252
|
+
|
242
253
|
it "should put object with callback" do
|
243
254
|
key = 'ruby'
|
244
255
|
stub_request(:put, object_url(key))
|
@@ -276,6 +287,37 @@ module Aliyun
|
|
276
287
|
.with { |req| req.headers.key?('X-Oss-Callback') }
|
277
288
|
end
|
278
289
|
|
290
|
+
it "should set custom headers when put object" do
|
291
|
+
key = 'ruby'
|
292
|
+
stub_request(:put, object_url(key))
|
293
|
+
|
294
|
+
@bucket.put_object(
|
295
|
+
key, headers: {'cache-control' => 'xxx', 'expires' => 'yyy'})
|
296
|
+
|
297
|
+
headers = {}
|
298
|
+
expect(WebMock).to have_requested(:put, object_url(key))
|
299
|
+
.with { |req| headers = req.headers }
|
300
|
+
expect(headers['Cache-Control']).to eq('xxx')
|
301
|
+
expect(headers['Expires']).to eq('yyy')
|
302
|
+
end
|
303
|
+
|
304
|
+
it "should set custom headers when append object" do
|
305
|
+
key = 'ruby'
|
306
|
+
query = {'append' => '', 'position' => 11}
|
307
|
+
stub_request(:post, object_url(key)).with(:query => query)
|
308
|
+
|
309
|
+
@bucket.append_object(
|
310
|
+
key, 11,
|
311
|
+
headers: {'CACHE-CONTROL' => 'nocache', 'EXPIRES' => 'seripxe'})
|
312
|
+
|
313
|
+
headers = {}
|
314
|
+
expect(WebMock).to have_requested(:post, object_url(key))
|
315
|
+
.with(:query => query)
|
316
|
+
.with { |req| headers = req.headers }
|
317
|
+
expect(headers['Cache-Control']).to eq('nocache')
|
318
|
+
expect(headers['Expires']).to eq('seripxe')
|
319
|
+
end
|
320
|
+
|
279
321
|
it "should get object to file" do
|
280
322
|
key = 'ruby'
|
281
323
|
# 100 KB
|
@@ -334,6 +376,19 @@ module Aliyun
|
|
334
376
|
:headers => {'Content-Type' => 'text/html'})
|
335
377
|
end
|
336
378
|
|
379
|
+
it "should append object with acl" do
|
380
|
+
key = 'ruby'
|
381
|
+
query = {'append' => '', 'position' => 11}
|
382
|
+
stub_request(:post, object_url(key)).with(:query => query)
|
383
|
+
|
384
|
+
@bucket.append_object(key, 11, :acl => ACL::PUBLIC_READ_WRITE)
|
385
|
+
|
386
|
+
expect(WebMock)
|
387
|
+
.to have_requested(:post, object_url(key))
|
388
|
+
.with(:query => query,
|
389
|
+
:headers => {'X-Oss-Object-Acl' => ACL::PUBLIC_READ_WRITE})
|
390
|
+
end
|
391
|
+
|
337
392
|
it "should answer object exists?" do
|
338
393
|
key = 'ruby'
|
339
394
|
|
@@ -115,27 +115,15 @@ module Aliyun
|
|
115
115
|
body: 'hello world',
|
116
116
|
host: 'server.com'
|
117
117
|
)
|
118
|
-
prg = []
|
119
118
|
@bucket.resumable_upload(
|
120
|
-
@object_key, @file,
|
121
|
-
:part_size => 10, :callback => callback) { |p| prg << p }
|
119
|
+
@object_key, @file, part_size: 10, callback: callback)
|
122
120
|
|
123
121
|
expect(WebMock).to have_requested(
|
124
122
|
:post, /#{object_url}\?uploads.*/).times(1)
|
125
123
|
|
126
|
-
part_numbers = Set.new([])
|
127
|
-
upload_ids = Set.new([])
|
128
|
-
|
129
124
|
expect(WebMock).to have_requested(
|
130
|
-
|
131
|
-
|
132
|
-
part_numbers << query['partNumber']
|
133
|
-
upload_ids << query['uploadId']
|
134
|
-
}.times(10)
|
135
|
-
|
136
|
-
expect(part_numbers.to_a).to match_array((1..10).map{ |x| x.to_s })
|
137
|
-
expect(upload_ids.to_a).to match_array(['upload_id'])
|
138
|
-
|
125
|
+
:put, /#{object_url}\?partNumber.*/)
|
126
|
+
.times(10)
|
139
127
|
expect(WebMock)
|
140
128
|
.to have_requested(
|
141
129
|
:post, /#{object_url}\?uploadId.*/)
|
@@ -143,7 +131,6 @@ module Aliyun
|
|
143
131
|
.times(1)
|
144
132
|
|
145
133
|
expect(File.exist?("#{@file}.cpt")).to be false
|
146
|
-
expect(prg.size).to eq(10)
|
147
134
|
end
|
148
135
|
|
149
136
|
it "should raise CallbackError when callback failed" do
|
@@ -162,28 +149,17 @@ module Aliyun
|
|
162
149
|
body: 'hello world',
|
163
150
|
host: 'server.com'
|
164
151
|
)
|
165
|
-
prg = []
|
166
152
|
expect {
|
167
153
|
@bucket.resumable_upload(
|
168
|
-
@object_key, @file,
|
169
|
-
:part_size => 10, :callback => callback) { |p| prg << p }
|
154
|
+
@object_key, @file, part_size: 10, callback: callback)
|
170
155
|
}.to raise_error(CallbackError, err(message))
|
171
156
|
|
172
157
|
expect(WebMock).to have_requested(
|
173
158
|
:post, /#{object_url}\?uploads.*/).times(1)
|
174
159
|
|
175
|
-
part_numbers = Set.new([])
|
176
|
-
upload_ids = Set.new([])
|
177
|
-
|
178
160
|
expect(WebMock).to have_requested(
|
179
|
-
|
180
|
-
|
181
|
-
part_numbers << query['partNumber']
|
182
|
-
upload_ids << query['uploadId']
|
183
|
-
}.times(10)
|
184
|
-
|
185
|
-
expect(part_numbers.to_a).to match_array((1..10).map{ |x| x.to_s })
|
186
|
-
expect(upload_ids.to_a).to match_array(['upload_id'])
|
161
|
+
:put, /#{object_url}\?partNumber.*/)
|
162
|
+
.times(10)
|
187
163
|
|
188
164
|
expect(WebMock)
|
189
165
|
.to have_requested(
|
@@ -192,7 +168,27 @@ module Aliyun
|
|
192
168
|
.times(1)
|
193
169
|
|
194
170
|
expect(File.exist?("#{@file}.cpt")).to be true
|
195
|
-
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should upload file with custom headers" do
|
174
|
+
stub_request(:post, /#{object_url}\?uploads.*/)
|
175
|
+
.to_return(:body => mock_txn_id('upload_id'))
|
176
|
+
stub_request(:put, /#{object_url}\?partNumber.*/)
|
177
|
+
stub_request(:post, /#{object_url}\?uploadId.*/)
|
178
|
+
|
179
|
+
@bucket.resumable_upload(
|
180
|
+
@object_key, @file,
|
181
|
+
part_size: 10,
|
182
|
+
headers: {'cache-CONTROL' => 'cacheit', 'CONTENT-disposition' => 'oh;yeah'})
|
183
|
+
|
184
|
+
headers = {}
|
185
|
+
expect(WebMock).to have_requested(
|
186
|
+
:post, /#{object_url}\?uploads.*/)
|
187
|
+
.with { |req| headers = req.headers }.times(1)
|
188
|
+
|
189
|
+
expect(headers['Cache-Control']).to eq('cacheit')
|
190
|
+
expect(headers['Content-Disposition']).to eq('oh;yeah')
|
191
|
+
expect(File.exist?("#{@file}.cpt")).to be false
|
196
192
|
end
|
197
193
|
|
198
194
|
it "should restart when begin txn fails" do
|
@@ -23,22 +23,22 @@ module Aliyun
|
|
23
23
|
key = 'helloworld'
|
24
24
|
date = 'Fri, 30 Oct 2015 07:21:00 GMT'
|
25
25
|
|
26
|
-
signature = Util.get_signature(key, 'GET', {'
|
26
|
+
signature = Util.get_signature(key, 'GET', {'date' => date}, {})
|
27
27
|
expect(signature).to eq("u8QKAAj/axKX4JhHXa5DYfYSPxE=")
|
28
28
|
|
29
29
|
signature = Util.get_signature(
|
30
|
-
key, 'PUT', {'
|
30
|
+
key, 'PUT', {'date' => date}, {:path => '/bucket'})
|
31
31
|
expect(signature).to eq("lMKrMCJIuGygd8UsdMA+S0QOAsQ=")
|
32
32
|
|
33
33
|
signature = Util.get_signature(
|
34
34
|
key, 'PUT',
|
35
|
-
{'
|
35
|
+
{'date' => date, 'x-oss-copy-source' => '/bucket/object-old'},
|
36
36
|
{:path => '/bucket/object-new'})
|
37
37
|
expect(signature).to eq("McYUmBaErN//yvE9voWRhCgvsIc=")
|
38
38
|
|
39
39
|
signature = Util.get_signature(
|
40
40
|
key, 'PUT',
|
41
|
-
{'
|
41
|
+
{'date' => date},
|
42
42
|
{:path => '/bucket/object-new',
|
43
43
|
:sub_res => {'append' => nil, 'position' => 0}})
|
44
44
|
expect(signature).to eq("7Oh2wobzeg6dw/cWYbF/2m6s6qc=")
|
data/tests/test_content_type.rb
CHANGED
@@ -43,15 +43,15 @@ class TestContentType < Minitest::Test
|
|
43
43
|
@types.each do |k, v|
|
44
44
|
key = get_key('from_key', k)
|
45
45
|
@bucket.put_object(key)
|
46
|
-
assert_equal v, @bucket.get_object(key).content_type
|
46
|
+
assert_equal v, @bucket.get_object(key).headers[:content_type]
|
47
47
|
|
48
48
|
copy_key = get_key('copy.from_key', k)
|
49
49
|
@bucket.copy_object(key, copy_key)
|
50
|
-
assert_equal v, @bucket.get_object(copy_key).content_type
|
50
|
+
assert_equal v, @bucket.get_object(copy_key).headers[:content_type]
|
51
51
|
|
52
52
|
append_key = get_key('append.from_key', k)
|
53
53
|
@bucket.append_object(append_key, 0)
|
54
|
-
assert_equal v, @bucket.get_object(append_key).content_type
|
54
|
+
assert_equal v, @bucket.get_object(append_key).headers[:content_type]
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
@@ -63,15 +63,15 @@ class TestContentType < Minitest::Test
|
|
63
63
|
|
64
64
|
key = get_key('from_file', k)
|
65
65
|
@bucket.put_object(key, :file => upload_file)
|
66
|
-
assert_equal v, @bucket.get_object(key).content_type
|
66
|
+
assert_equal v, @bucket.get_object(key).headers[:content_type]
|
67
67
|
|
68
68
|
append_key = get_key('append.from_file', k)
|
69
69
|
@bucket.append_object(append_key, 0, :file => upload_file)
|
70
|
-
assert_equal v, @bucket.get_object(append_key).content_type
|
70
|
+
assert_equal v, @bucket.get_object(append_key).headers[:content_type]
|
71
71
|
|
72
72
|
multipart_key = get_key('multipart.from_file', k)
|
73
73
|
@bucket.resumable_upload(multipart_key, upload_file)
|
74
|
-
assert_equal v, @bucket.get_object(multipart_key).content_type
|
74
|
+
assert_equal v, @bucket.get_object(multipart_key).headers[:content_type]
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
@@ -82,19 +82,19 @@ class TestContentType < Minitest::Test
|
|
82
82
|
|
83
83
|
key = get_key('from_user', k)
|
84
84
|
@bucket.put_object(key, :file => upload_file, :content_type => v)
|
85
|
-
assert_equal v, @bucket.get_object(key).content_type
|
85
|
+
assert_equal v, @bucket.get_object(key).headers[:content_type]
|
86
86
|
|
87
87
|
copy_key = get_key('copy.from_user', k)
|
88
88
|
@bucket.copy_object(key, copy_key, :content_type => v)
|
89
|
-
assert_equal v, @bucket.get_object(copy_key).content_type
|
89
|
+
assert_equal v, @bucket.get_object(copy_key).headers[:content_type]
|
90
90
|
|
91
91
|
append_key = get_key('append.from_user', k)
|
92
92
|
@bucket.append_object(append_key, 0, :file => upload_file, :content_type => v)
|
93
|
-
assert_equal v, @bucket.get_object(append_key).content_type
|
93
|
+
assert_equal v, @bucket.get_object(append_key).headers[:content_type]
|
94
94
|
|
95
95
|
multipart_key = get_key('multipart.from_file', k)
|
96
96
|
@bucket.resumable_upload(multipart_key, upload_file, :content_type => v)
|
97
|
-
assert_equal v, @bucket.get_object(multipart_key).content_type
|
97
|
+
assert_equal v, @bucket.get_object(multipart_key).headers[:content_type]
|
98
98
|
end
|
99
99
|
end
|
100
100
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'yaml'
|
3
|
+
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
|
4
|
+
require 'aliyun/oss'
|
5
|
+
require 'zlib'
|
6
|
+
|
7
|
+
class TestCustomHeaders < Minitest::Test
|
8
|
+
def setup
|
9
|
+
Aliyun::Common::Logging.set_log_level(Logger::DEBUG)
|
10
|
+
conf_file = '~/.oss.yml'
|
11
|
+
conf = YAML.load(File.read(File.expand_path(conf_file)))
|
12
|
+
client = Aliyun::OSS::Client.new(
|
13
|
+
:endpoint => conf['endpoint'],
|
14
|
+
:cname => conf['cname'],
|
15
|
+
:access_key_id => conf['access_key_id'],
|
16
|
+
:access_key_secret => conf['access_key_secret'])
|
17
|
+
@bucket = client.get_bucket(conf['bucket'])
|
18
|
+
|
19
|
+
@prefix = "tests/custom_headers/"
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_key(k)
|
23
|
+
"#{@prefix}#{k}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_custom_headers
|
27
|
+
key = get_key('ruby')
|
28
|
+
cache_control = 'max-age: 3600'
|
29
|
+
@bucket.put_object(key, headers: {'cache-control' => cache_control})
|
30
|
+
obj = @bucket.get_object(key)
|
31
|
+
assert_equal cache_control, obj.headers[:cache_control]
|
32
|
+
|
33
|
+
content_disposition = 'attachment; filename="fname.ext"'
|
34
|
+
@bucket.put_object(
|
35
|
+
key,
|
36
|
+
headers: {'cache-control' => cache_control,
|
37
|
+
'CONTENT-DISPOSITION' => content_disposition})
|
38
|
+
obj = @bucket.get_object(key)
|
39
|
+
assert_equal cache_control, obj.headers[:cache_control]
|
40
|
+
assert_equal content_disposition, obj.headers[:content_disposition]
|
41
|
+
|
42
|
+
content_encoding = 'deflate'
|
43
|
+
expires = (Time.now + 3600).httpdate
|
44
|
+
@bucket.put_object(
|
45
|
+
key,
|
46
|
+
headers: {'cache-control' => cache_control,
|
47
|
+
'CONTENT-DISPOSITION' => content_disposition,
|
48
|
+
'content-ENCODING' => content_encoding,
|
49
|
+
'EXPIRES' => expires }) do |s|
|
50
|
+
s << Zlib::Deflate.deflate('hello world')
|
51
|
+
end
|
52
|
+
|
53
|
+
content = ''
|
54
|
+
obj = @bucket.get_object(key) { |c| content << c }
|
55
|
+
assert_equal 'hello world', content
|
56
|
+
assert_equal cache_control, obj.headers[:cache_control]
|
57
|
+
assert_equal content_disposition, obj.headers[:content_disposition]
|
58
|
+
assert_equal content_encoding, obj.headers[:content_encoding]
|
59
|
+
assert_equal expires, obj.headers[:expires]
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_headers_overwrite
|
63
|
+
key = get_key('rails')
|
64
|
+
@bucket.put_object(
|
65
|
+
key,
|
66
|
+
content_type: 'text/html',
|
67
|
+
metas: {'hello' => 'world'},
|
68
|
+
headers: {'content-type' => 'application/json',
|
69
|
+
'x-oss-meta-hello' => 'bar'}) { |s| s << 'hello world' }
|
70
|
+
obj = @bucket.get_object(key)
|
71
|
+
|
72
|
+
assert_equal 'application/json', obj.headers[:content_type]
|
73
|
+
assert_equal ({'hello' => 'bar'}), obj.metas
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'yaml'
|
3
|
+
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
|
4
|
+
require 'aliyun/oss'
|
5
|
+
|
6
|
+
class TestObjectACL < Minitest::Test
|
7
|
+
def setup
|
8
|
+
Aliyun::Common::Logging.set_log_level(Logger::DEBUG)
|
9
|
+
conf_file = '~/.oss.yml'
|
10
|
+
conf = YAML.load(File.read(File.expand_path(conf_file)))
|
11
|
+
client = Aliyun::OSS::Client.new(
|
12
|
+
:endpoint => conf['endpoint'],
|
13
|
+
:cname => conf['cname'],
|
14
|
+
:access_key_id => conf['access_key_id'],
|
15
|
+
:access_key_secret => conf['access_key_secret'])
|
16
|
+
@bucket = client.get_bucket(conf['bucket'])
|
17
|
+
|
18
|
+
@prefix = "tests/object_acl/"
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_key(k)
|
22
|
+
"#{@prefix}#{k}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_put_object
|
26
|
+
key = get_key('put')
|
27
|
+
|
28
|
+
@bucket.put_object(key, acl: Aliyun::OSS::ACL::PRIVATE)
|
29
|
+
acl = @bucket.get_object_acl(key)
|
30
|
+
|
31
|
+
assert_equal Aliyun::OSS::ACL::PRIVATE, acl
|
32
|
+
|
33
|
+
@bucket.put_object(key, acl: Aliyun::OSS::ACL::PUBLIC_READ)
|
34
|
+
acl = @bucket.get_object_acl(key)
|
35
|
+
|
36
|
+
assert_equal Aliyun::OSS::ACL::PUBLIC_READ, acl
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_append_object
|
40
|
+
key = get_key('append-1')
|
41
|
+
|
42
|
+
@bucket.append_object(key, 0, acl: Aliyun::OSS::ACL::PRIVATE)
|
43
|
+
acl = @bucket.get_object_acl(key)
|
44
|
+
|
45
|
+
assert_equal Aliyun::OSS::ACL::PRIVATE, acl
|
46
|
+
|
47
|
+
key = get_key('append-2')
|
48
|
+
|
49
|
+
@bucket.put_object(key, acl: Aliyun::OSS::ACL::PUBLIC_READ)
|
50
|
+
acl = @bucket.get_object_acl(key)
|
51
|
+
|
52
|
+
assert_equal Aliyun::OSS::ACL::PUBLIC_READ, acl
|
53
|
+
end
|
54
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aliyun-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tianlong Wu
|
@@ -180,9 +180,11 @@ files:
|
|
180
180
|
- spec/aliyun/sts/client_spec.rb
|
181
181
|
- spec/aliyun/sts/util_spec.rb
|
182
182
|
- tests/test_content_type.rb
|
183
|
+
- tests/test_custom_headers.rb
|
183
184
|
- tests/test_encoding.rb
|
184
185
|
- tests/test_large_file.rb
|
185
186
|
- tests/test_multipart.rb
|
187
|
+
- tests/test_object_acl.rb
|
186
188
|
- tests/test_object_key.rb
|
187
189
|
- tests/test_resumable.rb
|
188
190
|
homepage: https://github.com/aliyun/aliyun-oss-ruby-sdk
|
@@ -223,8 +225,10 @@ test_files:
|
|
223
225
|
- spec/aliyun/sts/client_spec.rb
|
224
226
|
- spec/aliyun/sts/util_spec.rb
|
225
227
|
- tests/test_content_type.rb
|
228
|
+
- tests/test_custom_headers.rb
|
226
229
|
- tests/test_encoding.rb
|
227
230
|
- tests/test_large_file.rb
|
228
231
|
- tests/test_multipart.rb
|
232
|
+
- tests/test_object_acl.rb
|
229
233
|
- tests/test_object_key.rb
|
230
234
|
- tests/test_resumable.rb
|