oss-ruby 1.0.0.beta

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,159 @@
1
+ # Object API
2
+
3
+ Objects are the basic unit you can operation on OSS service. An object contains three parts: key, meta and data. Objects created through `put_object` cannot exceed 5GB, and the size of the object uploaded through 'multipart' cannot exceed 48.8TB.
4
+
5
+ * Object
6
+ * Object name conventions
7
+ * Upload an object through `put_object`
8
+ * Create a 'folder' in a bucket
9
+ * Set meta for an object
10
+ * Append object
11
+ * Multipart upload
12
+ * List all objects in a bucket
13
+ * Get object
14
+ * Get only meta of an object
15
+ * Delete object
16
+ * Copy object
17
+
18
+ #### Object name conventions
19
+
20
+ * Encode in 'UTF-8'.
21
+ * Cannot start with "\" or "/".
22
+ * Cannot contain "\r" or "\n".
23
+ * Length between 1-1023 bytes.
24
+
25
+ #### Upload an object through `put_object`
26
+ You can upload a file in two ways.
27
+ ```ruby
28
+ # method signature
29
+ put_object(bucket, object, body, headers = {})
30
+ ```
31
+ ```ruby
32
+ res = oss.put_object('bucket-name', 'object-name', 'string content')
33
+ p res.status # => 200
34
+ ```
35
+ ```ruby
36
+ # method signature
37
+ put_object_from_file(bucket, object, file_name, headers = {})
38
+ ```
39
+ ```ruby
40
+ res = oss.put_object_from_file('bucket-name', 'object-name', 'test.txt')
41
+ p res.status # => 200
42
+ ```
43
+
44
+ #### Create a 'folder' in a bucket
45
+ OSS service does not support 'folder' by default, but you can achieve it by create a object with empty data and name like 'folder_name/'.
46
+
47
+ ```ruby
48
+ res = oss.put_object('bucket-name', 'folder_name/', '')
49
+ p res.status # => 200
50
+ ```
51
+
52
+ #### Set meta for an object
53
+ You can store meta information in an object through `put_object`
54
+ Meta headers must start with 'x-oss-meta-'.
55
+
56
+ ```ruby
57
+ res = oss.put_object('bucket-name', 'object-name', 'string content', 'x-oss-meta-uploader' => 'Lucy')
58
+ p res.status # => 204
59
+ ```
60
+ An object can have multiple meta headers, size limit of meta information is 2KB.
61
+
62
+ #### Append object
63
+ Only 'Appendable Object' can be appended through `append_object`. Object created by `append_object` is 'Appendable Object', object created by `put_object` is 'Normal Object'.
64
+
65
+ You must set the right position to append. You can read the file length of object, and you can also get the right append position throught information in 'x-oss-next-append-position' of the response headers.
66
+
67
+ ```ruby
68
+ # method signature
69
+ append_object(bucket, object, body, position = 0, headers = {})
70
+ ```
71
+
72
+ ```ruby
73
+ res = oss.append_object('bucket-name', 'object-name', 'string-content', 0)
74
+ p res.status # => 200
75
+ p res.headers['x-oss-next-append-position'] # => 14
76
+ ```
77
+
78
+ #### Multipart upload
79
+ See information in [Multipart Upload](docs/multipart_upload.md)
80
+
81
+ #### List all objects in a bucket
82
+ You can list all objects through `get_bucket`. Additional parameters like 'prefix', 'marker', 'delimiter', 'max-keys' and 'encoding-type' are supported.
83
+ ```ruby
84
+ # method signature
85
+ get_bucket(name, params = {})
86
+ ```
87
+ ```ruby
88
+ res = oss.get_bucket('bucket-name')
89
+ p res.status # => 200
90
+
91
+ # use additional parameters
92
+ res = oss.get_bucket('bucket-name', 'MaxKeys' => 100)
93
+ p res.status # => 200
94
+ ```
95
+
96
+ #### Get object
97
+ ```ruby
98
+ # method signature
99
+ get_object(bucket, object, headers = {})
100
+ ```
101
+ ```ruby
102
+ res = oss.get_object('bucket-name', 'object-name')
103
+ p res.status # => 200
104
+ p res.body # => [344606 bytes of object data]
105
+ ```
106
+
107
+ #### Get only meta of an object
108
+ Sometimes you only need the meta information of an object. This API reponds with meta information in headers and no body attached.
109
+
110
+ ```ruby
111
+ # method signature
112
+ head_object(bucket, object, headers = {})
113
+ ```
114
+
115
+ ```ruby
116
+ res = oss.get_object('bucket-name', 'object-name')
117
+ p res.status # => 200
118
+ ```
119
+
120
+ #### Delete object
121
+ ```ruby
122
+ # method signature
123
+ delete_object(bucket, object)
124
+ ```
125
+
126
+ ```ruby
127
+ res = oss.delete_object('bucket-name', 'object-name')
128
+ p res.status # => 200
129
+ ```
130
+
131
+ You can also delete multiple objects at once using `delete_multiple_objects`.
132
+
133
+ ```ruby
134
+ # method signature
135
+ delete_multiple_objects(bucket, objects, quiet = false)
136
+ ```
137
+
138
+ ```ruby
139
+ res = oss.delete_multiple_objects('bucket-name', ['object1-name', 'object2-name'])
140
+ p res.status # => 200
141
+ ```
142
+
143
+ #### Copy object
144
+ Copying object is supported. But you can only copy objects inside the same region.
145
+ ```ruby
146
+ # method signature
147
+ copy_object(source_bucket, source_object, target_bucket, target_object, headers = {})
148
+ ```
149
+
150
+ ```ruby
151
+ res = oss.copy_object('source-bucket-name', 'source-object-name', 'target-bucket-name', 'target-object-name')
152
+ p res.status # => 200
153
+ ```
154
+
155
+ And you can use this method simple modify the meta information of an object.
156
+ ```ruby
157
+ res = oss.copy_object('target-bucket-name', 'target-object-name', 'target-bucket-name', 'target-object-name', "Content-Type" => "image/jpeg")
158
+ p res.status # => 200
159
+ ```
@@ -0,0 +1,57 @@
1
+ # Quick Start
2
+
3
+ This doc will show you basic operations of OSS APIs.
4
+
5
+ * Step 1: Initialize the `oss-ruby` SDK
6
+ * Step 2: Create a new bucket
7
+ * Step 3: Upload a file to a bucket
8
+ * Step 4: List all the objects of a bucket
9
+ * Step 5: Retrieve object from a bucket
10
+
11
+ #### Step 1: Initialization
12
+ `oss-ruby` requires you to initialize an instance before usage.
13
+
14
+ ```ruby
15
+ require 'oss'
16
+
17
+ oss = OSS.new({
18
+ endpoint: 'oss-cn-hangzhou.aliyuncs.com',
19
+ access_key_id: 'your_access_key',
20
+ access_key_secret: 'your_access_secret'
21
+ })
22
+ ```
23
+
24
+ #### Step 2: Create a new bucket
25
+ Bucket is the objects container of the OSS service. The bucket name must be unique.
26
+
27
+ ```ruby
28
+ res = oss.put_bucket 'bucket-name'
29
+ p res.status # => 200
30
+ ```
31
+
32
+ #### Step 3: Upload a file to a bucket
33
+ Object is the basic unit in OSS storage service. You can store a file in a bucket as one object.
34
+
35
+ ```ruby
36
+ res = oss.put_object_from_file('bucket-name', 'object-name', 'local-file.txt')
37
+ p res.status # => 200
38
+ ```
39
+
40
+ #### Step 4: List all the objects of a bucket
41
+ You can view all objects in a bucket through this API.
42
+
43
+ ```ruby
44
+ res = oss.get_bucket('bucket-name')
45
+ p res.status # => 200
46
+ ```
47
+
48
+ #### Step 5: Retrieve object from a bucket
49
+ Retrieve object from a bucket is pretty easy.
50
+
51
+ ```ruby
52
+ res = oss.get_object('bucket-name', 'object-name')
53
+ p res.status # => 200
54
+ p res.body # => [344606 bytes of object data]
55
+ ```
56
+
57
+ And you can get meta information of the object from the response headers.
data/lib/oss.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'faraday'
2
+ require 'nokogiri'
3
+
4
+ require 'oss/version'
5
+ require 'oss/error'
6
+ require 'oss/utils'
7
+ require 'oss/config'
8
+ require 'oss/response'
9
+ require 'oss/client'
10
+ require 'oss/service'
11
+ require 'oss/bucket'
12
+ require 'oss/object'
13
+ require 'oss/base'
14
+
15
+ module OSS
16
+ class << self
17
+ def new(options)
18
+ OSS::Base.new(options)
19
+ end
20
+ end
21
+ end
data/lib/oss/base.rb ADDED
@@ -0,0 +1,65 @@
1
+ module OSS
2
+ class Base
3
+ extend Forwardable
4
+ attr_reader :config
5
+
6
+ def initialize(options = {})
7
+ @config = OSS::Config.new(
8
+ OSS::Utils.indifferent_hash(options)
9
+ )
10
+ end
11
+
12
+ def_delegators :bucket,
13
+ :get_service,
14
+ :put_bucket,
15
+ :put_bucket_acl,
16
+ :put_bucket_logging,
17
+ :put_bucket_website,
18
+ :put_bucket_referer,
19
+ :put_bucket_lifecycle,
20
+ :get_bucket,
21
+ :get_bucket_acl,
22
+ :get_bucket_location,
23
+ :get_bucket_logging,
24
+ :get_bucket_website,
25
+ :get_bucket_referer,
26
+ :get_bucket_lifecycle,
27
+ :delete_bucket,
28
+ :delete_bucket_logging,
29
+ :delete_bucket_website,
30
+ :delete_bucket_lifecycle,
31
+ :put_bucket_cors,
32
+ :get_bucket_cors,
33
+ :delete_bucket_cors
34
+
35
+ def_delegators :object,
36
+ :put_object,
37
+ :put_object_from_file,
38
+ :copy_object,
39
+ :get_object,
40
+ :append_object,
41
+ :delete_object,
42
+ :delete_multiple_objects,
43
+ :head_object,
44
+ :put_object_acl,
45
+ :get_object_acl,
46
+ :post_object,
47
+ :init_multi_upload,
48
+ :upload_object_part,
49
+ :upload_object_part_copy,
50
+ :complete_multi_upload,
51
+ :abort_multi_upload,
52
+ :list_multi_upload,
53
+ :list_object_parts
54
+
55
+ private
56
+
57
+ def bucket
58
+ @bucket ||= OSS::Bucket.new(config)
59
+ end
60
+
61
+ def object
62
+ @object ||= OSS::Object.new(config)
63
+ end
64
+ end
65
+ end
data/lib/oss/bucket.rb ADDED
@@ -0,0 +1,202 @@
1
+ module OSS
2
+ class Bucket < Service
3
+ # params keys: prefix, marker, max-keys
4
+ def get_service(params = {})
5
+ client.run :get, '/', params
6
+ end
7
+
8
+ def put_bucket(name, permission = 'private', location = 'oss-cn-hangzhou')
9
+ body = '<?xml version="1.0" encoding="UTF-8"?>' \
10
+ '<CreateBucketConfiguration>' \
11
+ "<LocationConstraint>#{location}</LocationConstraint>" \
12
+ '</CreateBucketConfiguration>'
13
+ headers = {
14
+ 'x-oss-acl' => permission,
15
+ 'Content-Type' => 'application/xml'
16
+ }
17
+ options = setup_options(name)
18
+ client(options).run :put, '/', body, headers
19
+ end
20
+
21
+ # permission: public-read-write,public-read, private
22
+ def put_bucket_acl(name, permission)
23
+ headers = {
24
+ 'x-oss-acl' => permission
25
+ }
26
+ options = setup_options(name, 'acl')
27
+ client(options).run :put, '?acl', nil, headers
28
+ end
29
+
30
+ def put_bucket_logging(source, target = nil, prefix = nil)
31
+ body = '<?xml version="1.0" encoding="UTF-8"?><BucketLoggingStatus>'
32
+ if target
33
+ body += "<LoggingEnabled><TargetBucket>#{target}</TargetBucket>"
34
+ body += "<TargetPrefix>#{prefix}</TargetPrefix>" if prefix
35
+ body += '</LoggingEnabled>'
36
+ end
37
+ body += '</BucketLoggingStatus>'
38
+
39
+ headers = {
40
+ 'Content-Type' => 'application/xml'
41
+ }
42
+
43
+ options = setup_options(source, 'logging')
44
+ client(options).run :put, '?logging', body, headers
45
+ end
46
+
47
+ def put_bucket_website(name, index, error)
48
+ body = '<?xml version="1.0" encoding="UTF-8"?><WebsiteConfiguration>' \
49
+ "<IndexDocument><Suffix>#{index}</Suffix></IndexDocument>"
50
+ if error
51
+ body += "<ErrorDocument><Key>#{error}</Key></ErrorDocument>"
52
+ end
53
+ body += '</WebsiteConfiguration>'
54
+
55
+ headers = {
56
+ 'Content-Type' => 'application/xml'
57
+ }
58
+
59
+ options = setup_options(name, 'website')
60
+ client(options).run :put, '?website', body, headers
61
+ end
62
+
63
+ def put_bucket_website(name, index, error)
64
+ body = '<?xml version="1.0" encoding="UTF-8"?><WebsiteConfiguration>' \
65
+ "<IndexDocument><Suffix>#{index}</Suffix></IndexDocument>"
66
+ if error
67
+ body += "<ErrorDocument><Key>#{error}</Key></ErrorDocument>"
68
+ end
69
+ body += '</WebsiteConfiguration>'
70
+
71
+ headers = {
72
+ 'Content-Type' => 'application/xml'
73
+ }
74
+
75
+ options = setup_options(name, 'website')
76
+ client(options).run :put, '?website', body, headers
77
+ end
78
+
79
+ def put_bucket_referer(name, allow_empty_referer = true, referers=[])
80
+ body = '<?xml version="1.0" encoding="UTF-8"?><RefererConfiguration>' \
81
+ "<AllowEmptyReferer>#{allow_empty_referer}</AllowEmptyReferer >" \
82
+ "<RefererList>"
83
+ referers.each do |referer|
84
+ body += "<Referer>#{referer}</Referer>"
85
+ end
86
+ body += '</RefererList></RefererConfiguration>'
87
+
88
+ headers = {
89
+ 'Content-Type' => 'application/xml'
90
+ }
91
+
92
+ options = setup_options(name, 'referer')
93
+ client(options).run :put, '?referer', body, headers
94
+ end
95
+
96
+ # status: Enabled, Disabled
97
+ def put_bucket_lifecycle(name, rules = [])
98
+ body = '<?xml version="1.0" encoding="UTF-8"?><LifecycleConfiguration>'
99
+ rules.each do |rule|
100
+ rule_content = '<Rule>'
101
+ rule_content += "<ID>#{rule[:id]}</ID>" if rule[:id]
102
+ rule_content += "<Prefix>#{rule[:prefix]}</Prefix>" if rule[:prefix]
103
+ rule_content += "<Status>#{rule[:status]}</Status>"
104
+ expiration =
105
+ if rule[:days]
106
+ "<Days>#{rule[:days]}</Days>"
107
+ else
108
+ "<Date>#{rule[:date]}</Date>"
109
+ end
110
+ rule_content += "<Expiration>#{expiration}</Expiration></Rule>"
111
+ body += rule_content
112
+ end
113
+
114
+ body += '</LifecycleConfiguration>'
115
+
116
+ headers = {
117
+ 'Content-Type' => 'application/xml'
118
+ }
119
+
120
+ options = setup_options(name, 'lifecycle')
121
+ client(options).run :put, '?lifecycle', body, headers
122
+ end
123
+
124
+ # params keys: prefix, marker, delimiter, max-keys, encoding-type
125
+ def get_bucket(name, params = {})
126
+ options = setup_options(name)
127
+ client(options).run :get, '/', params
128
+ end
129
+
130
+ [:acl, :location, :logging, :website, :referer, :lifecycle, :cors].each do |sub_resource|
131
+ define_method("get_bucket_#{sub_resource}".to_sym) do |name|
132
+ get_bucket_sub_resource(name, sub_resource)
133
+ end
134
+ end
135
+
136
+ def delete_bucket(name)
137
+ options = setup_options(name)
138
+ client(options).run :delete, '/'
139
+ end
140
+
141
+ [:logging, :website, :lifecycle, :cors].each do |sub_resource|
142
+ define_method("delete_bucket_#{sub_resource}".to_sym) do |name|
143
+ delete_bucket_sub_resource(name, sub_resource)
144
+ end
145
+ end
146
+
147
+ def put_bucket_cors(name, rules)
148
+ body = '<?xml version="1.0" encoding="UTF-8"?><CORSConfiguration>'
149
+ rules.each do |rule|
150
+ rule_content = '<CORSRule>'
151
+ rule_content += cors_rule_content_generator(rule, 'AllowedOrigin')
152
+ rule_content += cors_rule_content_generator(rule, 'AllowedMethod')
153
+ rule_content += cors_rule_content_generator(rule, 'AllowedHeader')
154
+ rule_content += cors_rule_content_generator(rule, 'ExposeHeader')
155
+ rule_content += cors_rule_content_generator(rule, 'MaxAgeSeconds', false)
156
+ rule_content += '</CORSRule>'
157
+ body += rule_content
158
+ end
159
+ body += '</CORSConfiguration>'
160
+
161
+ headers = {
162
+ 'Content-Type' => 'application/xml'
163
+ }
164
+
165
+ options = setup_options(name, 'cors')
166
+ client(options).run :put, '?cors', body, headers
167
+ end
168
+
169
+ private
170
+
171
+ def cors_rule_content_generator(rule, key, allow_multi = true)
172
+ options = rule[key]
173
+ return '' unless options
174
+ if allow_multi
175
+ options = options.is_a?(Array) ? options : [options]
176
+ options.reduce('') do |content, option|
177
+ content + "<#{key}>#{option}</#{key}>"
178
+ end
179
+ else
180
+ "<#{key}>#{options}</#{key}>"
181
+ end
182
+ end
183
+
184
+ def delete_bucket_sub_resource(name, sub_resource)
185
+ options = setup_options(name, sub_resource)
186
+ client(options).run :delete, "?#{sub_resource}"
187
+ end
188
+
189
+ def get_bucket_sub_resource(name, sub_resource)
190
+ options = setup_options(name, sub_resource)
191
+ client(options).run :get, '/', "#{sub_resource}" => nil
192
+ end
193
+
194
+ def setup_options(bucket, sub_resource = nil)
195
+ {
196
+ subdomain: bucket,
197
+ resource: "/#{bucket}/",
198
+ sub_resource: sub_resource
199
+ }
200
+ end
201
+ end
202
+ end