aliyun-oss-sdk 0.0.3 → 0.1.0

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +17 -0
  3. data/Gemfile +1 -0
  4. data/README.md +12 -10
  5. data/Rakefile +10 -0
  6. data/aliyun-oss.gemspec +2 -2
  7. data/lib/aliyun/oss.rb +4 -11
  8. data/lib/aliyun/oss/authorization.rb +59 -27
  9. data/lib/aliyun/oss/client.rb +137 -62
  10. data/lib/aliyun/oss/client/bucket_multiparts.rb +43 -0
  11. data/lib/aliyun/oss/client/bucket_objects.rb +111 -0
  12. data/lib/aliyun/oss/client/buckets.rb +50 -0
  13. data/lib/aliyun/oss/client/clients.rb +54 -0
  14. data/lib/aliyun/oss/error.rb +43 -0
  15. data/lib/aliyun/oss/http.rb +65 -23
  16. data/lib/aliyun/oss/struct.rb +26 -0
  17. data/lib/aliyun/oss/struct/bucket.rb +252 -0
  18. data/lib/aliyun/oss/struct/cors.rb +65 -0
  19. data/lib/aliyun/oss/struct/lifecycle.rb +73 -0
  20. data/lib/aliyun/oss/struct/logging.rb +33 -0
  21. data/lib/aliyun/oss/struct/multipart.rb +101 -0
  22. data/lib/aliyun/oss/struct/object.rb +71 -0
  23. data/lib/aliyun/oss/struct/part.rb +48 -0
  24. data/lib/aliyun/oss/struct/referer.rb +21 -0
  25. data/lib/aliyun/oss/struct/website.rb +13 -0
  26. data/lib/aliyun/oss/utils.rb +41 -1
  27. data/lib/aliyun/oss/version.rb +1 -1
  28. data/lib/aliyun/oss/xml_generator.rb +174 -0
  29. data/todo.md +5 -0
  30. data/wiki/bucket.md +20 -20
  31. data/wiki/cors.md +59 -0
  32. data/wiki/error.md +42 -31
  33. data/wiki/get_start.md +24 -7
  34. data/wiki/installation.md +2 -2
  35. data/wiki/lifecycle.md +75 -0
  36. data/wiki/multipart.md +7 -5
  37. data/wiki/object.md +16 -12
  38. metadata +48 -6
  39. data/lib/aliyun/oss/multipart/part.rb +0 -32
  40. data/lib/aliyun/oss/rule/cors.rb +0 -63
  41. data/lib/aliyun/oss/rule/lifecycle.rb +0 -61
@@ -0,0 +1,43 @@
1
+ module Aliyun
2
+ module Oss
3
+ class Client
4
+ module BucketMultiparts
5
+ # Init a Multipart Upload Event
6
+ #
7
+ # @param (see #bucket_init_multipart)
8
+ #
9
+ # @raise [RequestError]
10
+ #
11
+ # @return [Aliyun::Oss::Struct::Multipart]
12
+ #
13
+ # @see Client#bucket_init_multipart
14
+ def init(*args)
15
+ result = client.bucket_init_multipart(*args).parsed_response
16
+
17
+ multipart = Utils.dig_value(result, 'InitiateMultipartUploadResult')
18
+ Struct::Multipart.new((multipart || {}).merge(client: client))
19
+ end
20
+
21
+ # List exist Multipart Upload Events of bucket
22
+ #
23
+ # @param (see #bucket_list_multiparts)
24
+ #
25
+ # @option (see #bucket_list_multiparts)
26
+ #
27
+ # @raise [RequestError]
28
+ #
29
+ # @return [Array<Aliyun::Oss::Struct::Multipart>]
30
+ #
31
+ # @see Client#bucket_list_multiparts
32
+ def list(*args)
33
+ result = client.bucket_list_multiparts(*args).parsed_response
34
+
35
+ multipart_keys = %w(ListMultipartUploadsResult Upload)
36
+ Utils.wrap(Utils.dig_value(result, *multipart_keys)).map do |multipart|
37
+ Struct::Multipart.new(multipart.merge(client: client))
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,111 @@
1
+ module Aliyun
2
+ module Oss
3
+ class Client
4
+ module BucketObjects
5
+ # List objects of bucket
6
+ #
7
+ # @param (see #bucket_list_objects)
8
+ #
9
+ # @option (see #bucket_list_objects)
10
+ #
11
+ # @raise [RequestError]
12
+ #
13
+ # @return [Array<Aliyun::Oss::Struct::Object>]
14
+ #
15
+ # @see Client#bucket_list_objects
16
+ def list(*args)
17
+ result = client.bucket_list_objects(*args).parsed_response
18
+
19
+ object_keys = %w(ListBucketResult Contents)
20
+ Utils.wrap(Utils.dig_value(result, *object_keys)).map do |object|
21
+ Struct::Object.new(object.merge(client: client))
22
+ end
23
+ end
24
+
25
+ # create object of bucket
26
+ #
27
+ # @param (see #bucket_create_object)
28
+ #
29
+ # @raise [RequestError]
30
+ #
31
+ # @return [true]
32
+ #
33
+ # @see Client#bucket_create_object
34
+ def create(*args)
35
+ !!client.bucket_create_object(*args)
36
+ end
37
+
38
+ # Delete object for bucket
39
+ #
40
+ # @param (see #bucket_delete_object)
41
+ #
42
+ # @raise [RequestError]
43
+ #
44
+ # @return [true]
45
+ #
46
+ # @see Client#bucket_delete_object
47
+ def delete(*args)
48
+ !!client.bucket_delete_object(*args)
49
+ end
50
+
51
+ # Delete objects for bucket
52
+ #
53
+ # @param (see #bucket_delete_objects)
54
+ #
55
+ # @raise [RequestError]
56
+ #
57
+ # @return [true]
58
+ #
59
+ # @see Client#bucket_delete_objects
60
+ def delete_multiple(*args)
61
+ !!client.bucket_delete_objects(*args)
62
+ end
63
+
64
+ # Copy from existing object
65
+ #
66
+ # @param (see #bucket_copy_object)
67
+ #
68
+ # @option (see #bucket_copy_object)
69
+ #
70
+ # @raise [RequestError]
71
+ #
72
+ # @return [true]
73
+ #
74
+ # @see Client#bucket_copy_object
75
+ def copy(*args)
76
+ !!client.bucket_copy_object(*args)
77
+ end
78
+
79
+ # Get Object
80
+ #
81
+ # @param (see #bucket_get_object)
82
+ #
83
+ # @option (see #bucket_get_object)
84
+ #
85
+ # @raise [RequestError]
86
+ #
87
+ # @return [String]
88
+ #
89
+ # @see Client#bucekt_get_object
90
+ def get(*args)
91
+ client.bucket_get_object(*args).body
92
+ end
93
+
94
+ # Append data to a object, will create Appendable object
95
+ #
96
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject Append Object
97
+ #
98
+ # @param (see #bucket_append_object)
99
+ #
100
+ # @raise (see #bucket_append_object)
101
+ #
102
+ # @return [true]
103
+ #
104
+ # @see Client#bucket_append_object
105
+ def append(*args)
106
+ !!client.bucket_append_object(*args)
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,50 @@
1
+ module Aliyun
2
+ module Oss
3
+ class Client
4
+ module Buckets
5
+ # List buckets
6
+ #
7
+ # @param (see #list_buckets)
8
+ # @option (see #list_buckets)
9
+ #
10
+ # @return [Array<Aliyun::Oss::Struct::Bucket>]
11
+ #
12
+ # @see Client#list_buckets
13
+ def list(options = {})
14
+ result = client.list_buckets(options).parsed_response
15
+
16
+ bucket_keys = %w(ListAllMyBucketsResult Buckets Bucket)
17
+ Utils.wrap(Utils.dig_value(result, *bucket_keys)).map do |bucket_hash|
18
+ Struct::Bucket.new(bucket_hash).tap do |bucket|
19
+ dup_client = client.clone
20
+ dup_client.bucket = bucket.name
21
+ bucket.client = dup_client
22
+ end
23
+ end
24
+ end
25
+
26
+ # Create bucket
27
+ #
28
+ # @param (see #bucket_create)
29
+ #
30
+ # @return [true]
31
+ #
32
+ # @see Client#bucket_create
33
+ def create(*args)
34
+ !!client.bucket_create(*args)
35
+ end
36
+
37
+ # Delete bucket
38
+ #
39
+ # @param (see #bucket_delete)
40
+ #
41
+ # @return [true]
42
+ #
43
+ # @see Client#bucket_delete
44
+ def delete(*args)
45
+ !!client.bucket_delete(*args)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,54 @@
1
+ module Aliyun
2
+ module Oss
3
+ #
4
+ # Here is some services used to make object based API possible, they are all contains a reference to instance of client, which used to do the real job.
5
+ #
6
+ # buckets: used to do many buckets operations eg: #list, #create, #delete
7
+ #
8
+ # client.buckets
9
+ #
10
+ # bucket_objects: used to do some operation on objects eg: #list, #create, :delete, #copy
11
+ #
12
+ # client.bucket_objects
13
+ #
14
+ # bucket_multiparts: used to do some operation for multiparts eg: #init, #list
15
+ #
16
+ # client.bucket_multiparts
17
+ #
18
+ #
19
+ class Client
20
+ def buckets
21
+ @services[:buckets] ||= Client::BucketsService.new(self)
22
+ end
23
+
24
+ def bucket_objects
25
+ @services[:bucket_objects] ||= Client::BucketObjectsService.new(self)
26
+ end
27
+
28
+ def bucket_multiparts
29
+ @services[:bucket_multiparts] ||= \
30
+ Client::BucketMultipartsService.new(self)
31
+ end
32
+
33
+ ClientService = ::Struct.new(:client)
34
+
35
+ require 'aliyun/oss/client/buckets'
36
+
37
+ class BucketsService < ClientService
38
+ include Client::Buckets
39
+ end
40
+
41
+ require 'aliyun/oss/client/bucket_objects'
42
+
43
+ class BucketObjectsService < ClientService
44
+ include Client::BucketObjects
45
+ end
46
+
47
+ require 'aliyun/oss/client/bucket_multiparts'
48
+
49
+ class BucketMultipartsService < ClientService
50
+ include Client::BucketMultiparts
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,43 @@
1
+ module Aliyun
2
+ module Oss
3
+ class Error < StandardError; end
4
+
5
+ # [Aliyun::Oss::RequestError] when OSS give a Non 2xx response
6
+ class RequestError < Error
7
+ # Error Code defined by OSS
8
+ attr_reader :code
9
+
10
+ # Error Message defined by OSS
11
+ attr_reader :message
12
+
13
+ # It's the UUID to uniquely identifies this request;
14
+ # When you can't solve the problem, you can request help from the OSS development engineer with the RequestId.
15
+ attr_reader :request_id
16
+
17
+ # The Origin Httparty Response
18
+ attr_reader :origin_response
19
+
20
+ def initialize(response)
21
+ if (error_values = response.parsed_response['Error']).empty?
22
+ @code = response.code
23
+ @message = response.message
24
+ else
25
+ @code = error_values['Code']
26
+ @message = error_values['Message']
27
+ end
28
+ @request_id = response.headers['x-oss-request-id']
29
+ @origin_response = response
30
+ super("#{@request_id} - #{@code}: #{@message}")
31
+ end
32
+ end
33
+
34
+ class MultipartPartNumberEmpty < Error; end
35
+ class MultipartUploadIdEmpty < Error; end
36
+ class MultipartSourceBucketEmptyError < Error; end
37
+ class MultipartSourceKeyEmptyError < Error; end
38
+ class MultipartPartsEmptyError < Error; end
39
+
40
+ class InvalidCorsRuleError < Error; end
41
+ class InvalidLifeCycleRuleError < Error; end
42
+ end
43
+ end
@@ -1,3 +1,6 @@
1
+ require 'httparty'
2
+ require 'aliyun/oss/error'
3
+
1
4
  module Aliyun
2
5
  module Oss
3
6
  class Http # nodoc
@@ -39,25 +42,58 @@ module Aliyun
39
42
  private
40
43
 
41
44
  def request(verb, resource, options = {})
42
- headers = options.delete(:headers) || {}
43
- headers = default_headers.merge!(headers)
45
+ query = options.fetch(:query, {})
46
+ headers = options.fetch(:headers, {})
47
+ body = options.delete(:body)
48
+
49
+ append_headers!(headers, verb, body, options)
50
+
51
+ path = api_endpoint(headers['Host']) + resource
52
+ options = { headers: headers, query: query, body: body }
44
53
 
45
- if options[:body]
46
- headers.merge!('Content-MD5' => Utils.md5_digest(options[:body])) unless headers.key?('Content-MD5')
47
- headers.merge!('Content-Length' => Utils.content_size(options[:body]).to_s) unless headers.key?('Content-Length')
54
+ wrap(HTTParty.__send__(verb.downcase, path, options))
55
+ end
56
+
57
+ def wrap(response)
58
+ case response.code
59
+ when 200..299
60
+ response
61
+ else
62
+ fail RequestError, response
48
63
  end
64
+ end
49
65
 
50
- headers.merge!('Host' => get_host(options))
66
+ def append_headers!(headers, verb, body, options)
67
+ append_default_headers!(headers)
68
+ append_body_headers!(headers, body)
69
+ append_host_headers!(headers, options[:bucket], options[:location])
70
+ append_authorization_headers!(headers, verb, options)
71
+ end
51
72
 
52
- auth_key = get_auth_key(options
53
- .merge(verb: verb, headers: headers, date: headers['Date']))
54
- headers.merge!('Authorization' => auth_key)
73
+ def append_default_headers!(headers)
74
+ headers.merge!(default_headers)
75
+ end
55
76
 
56
- path = get_uri(headers['Host'], resource)
57
- options = Utils
58
- .hash_slice(options.merge(headers: headers), :query, :headers, :body)
77
+ def append_body_headers!(headers, body)
78
+ return headers unless body
59
79
 
60
- HTTParty.__send__(verb.downcase, path, options)
80
+ unless headers.key?('Content-MD5')
81
+ headers.merge!('Content-MD5' => Utils.md5_digest(body))
82
+ end
83
+
84
+ return if headers.key?('Content-Length')
85
+ headers.merge!('Content-Length' => Utils.content_size(body).to_s)
86
+ end
87
+
88
+ def append_host_headers!(headers, bucket, location)
89
+ headers.merge!('Host' => get_host(bucket, location))
90
+ end
91
+
92
+ def append_authorization_headers!(headers, verb, options)
93
+ auth_key = get_auth_key(
94
+ options.merge(verb: verb, headers: headers, date: headers['Date'])
95
+ )
96
+ headers.merge!('Authorization' => auth_key)
61
97
  end
62
98
 
63
99
  def get_auth_key(options)
@@ -66,28 +102,34 @@ module Aliyun
66
102
 
67
103
  def default_headers
68
104
  {
69
- 'User-Agent' => "aliyun-oss-sdk-ruby/#{Aliyun::Oss::VERSION} " \
70
- "(#{RbConfig::CONFIG['host_os']} ruby-#{RbConfig::CONFIG['ruby_version']})",
105
+ 'User-Agent' => user_agent,
71
106
  'Date' => Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
72
107
  }
73
108
  end
74
109
 
75
- def get_host(options)
76
- if options[:location] && options[:bucket]
77
- "#{options[:bucket]}.#{options[:location]}.aliyuncs.com"
78
- elsif options[:bucket]
79
- "#{options[:bucket]}.#{@host}"
110
+ def get_host(bucket, location)
111
+ if location && bucket
112
+ "#{bucket}.#{location}.aliyuncs.com"
113
+ elsif bucket
114
+ "#{bucket}.#{@host}"
80
115
  else
81
116
  @host
82
117
  end
83
118
  end
84
119
 
85
120
  def default_content_type
86
- { 'Content-Type' => 'application/x-www-form-urlencoded' }
121
+ {
122
+ 'Content-Type' => 'application/x-www-form-urlencoded'
123
+ }
124
+ end
125
+
126
+ def api_endpoint(host)
127
+ "http://#{host}"
87
128
  end
88
129
 
89
- def get_uri(host, resource)
90
- "http://#{host}#{resource}"
130
+ def user_agent
131
+ "aliyun-oss-sdk-ruby/#{Aliyun::Oss::VERSION} " \
132
+ "(#{RbConfig::CONFIG['host_os']} ruby-#{RbConfig::CONFIG['ruby_version']})"
91
133
  end
92
134
  end
93
135
  end
@@ -0,0 +1,26 @@
1
+ module Aliyun
2
+ module Oss
3
+ module Struct
4
+ class Base
5
+ def initialize(attributes = {})
6
+ attributes.each do |key, value|
7
+ m = "#{Utils.underscore(key)}=".to_sym
8
+ send(m, value) if self.respond_to?(m)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ require 'aliyun/oss/struct/bucket'
17
+ require 'aliyun/oss/struct/object'
18
+ require 'aliyun/oss/struct/multipart'
19
+
20
+ require 'aliyun/oss/struct/cors'
21
+ require 'aliyun/oss/struct/lifecycle'
22
+ require 'aliyun/oss/struct/referer'
23
+ require 'aliyun/oss/struct/website'
24
+ require 'aliyun/oss/struct/logging'
25
+
26
+ require 'aliyun/oss/struct/part'