aliyun-oss-sdk 0.0.3 → 0.1.0

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