sndacs 0.0.1 → 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.
- data/Gemfile.lock +0 -2
- data/README.rdoc +21 -3
- data/lib/sndacs/bucket.rb +100 -52
- data/lib/sndacs/buckets_extension.rb +5 -0
- data/lib/sndacs/config.rb +59 -0
- data/lib/sndacs/connection.rb +38 -13
- data/lib/sndacs/exceptions.rb +6 -3
- data/lib/sndacs/object.rb +35 -24
- data/lib/sndacs/objects_extension.rb +2 -0
- data/lib/sndacs/parser.rb +31 -8
- data/lib/sndacs/request.rb +8 -1
- data/lib/sndacs/service.rb +38 -27
- data/lib/sndacs/signature.rb +6 -31
- data/lib/sndacs/version.rb +1 -1
- data/lib/sndacs.rb +28 -2
- data/sndacs.gemspec +5 -5
- data/spec/sndacs/bucket_spec.rb +180 -0
- data/spec/sndacs/object_spec.rb +167 -0
- data/spec/sndacs/service_spec.rb +30 -19
- data/spec/spec_helper.rb +19 -0
- metadata +90 -66
- data/test/bucket_test.rb +0 -215
- data/test/connection_test.rb +0 -214
- data/test/object_test.rb +0 -205
- data/test/service_test.rb +0 -111
- data/test/signature_test.rb +0 -205
- data/test/test_helper.rb +0 -3
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -13,8 +13,26 @@ bases on the s3 gem: https://github.com/qoobaa/s3
|
|
13
13
|
=== Initialize the service
|
14
14
|
|
15
15
|
require "sndacs"
|
16
|
-
|
17
|
-
|
16
|
+
|
17
|
+
service = Sndacs::Service.new(:access_key_id => '...'
|
18
|
+
:secret_access_key => '...')
|
19
|
+
#=> #<Sndacs::Service:...>
|
20
|
+
|
21
|
+
or use even more flexible config style
|
22
|
+
|
23
|
+
require "sndacs"
|
24
|
+
|
25
|
+
# Setup global default configurations, see Sndacs::Config for more info
|
26
|
+
Config.access_key_id = '...'
|
27
|
+
Config.secret_access_key = '...'
|
28
|
+
Config.host = 'storage.grandcloud.cn'
|
29
|
+
Config.content_host = 'storage.sdcloud.cn'
|
30
|
+
Config.proxy = nil
|
31
|
+
Config.timeout = 60
|
32
|
+
Config.use_ssl = false
|
33
|
+
Config.chunk_size = 1048576
|
34
|
+
Config.debug = false
|
35
|
+
service = Sndacs::Service.new
|
18
36
|
#=> #<Sndacs::Service:...>
|
19
37
|
|
20
38
|
=== List buckets
|
@@ -64,7 +82,7 @@ bases on the s3 gem: https://github.com/qoobaa/s3
|
|
64
82
|
new_object.save
|
65
83
|
#=> true
|
66
84
|
|
67
|
-
Please note that new objects are created with "
|
85
|
+
Please note that new objects are created with "private" ACL by
|
68
86
|
default.
|
69
87
|
|
70
88
|
== See also
|
data/lib/sndacs/bucket.rb
CHANGED
@@ -1,83 +1,101 @@
|
|
1
1
|
module Sndacs
|
2
|
+
|
2
3
|
class Bucket
|
3
4
|
include Parser
|
4
5
|
include Proxies
|
5
6
|
extend Forwardable
|
6
7
|
|
7
|
-
attr_reader :name, :service
|
8
|
+
attr_reader :name, :location, :service
|
8
9
|
|
9
10
|
def_instance_delegators :service, :service_request
|
10
11
|
private_class_method :new
|
11
12
|
|
13
|
+
# Compares the bucket with other bucket. Returns true if the names
|
14
|
+
# of the buckets are the same, and both have the same locations and services
|
15
|
+
# (see Service equality)
|
16
|
+
def ==(other)
|
17
|
+
self.name == other.name and self.location == other.location and self.service == other.service
|
18
|
+
end
|
19
|
+
|
12
20
|
# Retrieves the bucket information from the server. Raises an
|
13
|
-
#
|
21
|
+
# Sndacs::Error exception if the bucket doesn't exist or you don't
|
14
22
|
# have access to it, etc.
|
15
23
|
def retrieve
|
16
24
|
bucket_headers
|
25
|
+
|
17
26
|
self
|
18
27
|
end
|
19
28
|
|
20
|
-
# Returns location of the bucket, e.g. "
|
29
|
+
# Returns location of the bucket, e.g. "huabei-1"
|
21
30
|
def location(reload = false)
|
22
31
|
return @location if defined?(@location) and not reload
|
32
|
+
|
23
33
|
@location = location_constraint
|
24
34
|
end
|
25
35
|
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
36
|
+
# Saves the newly built bucket. Raises Sndacs::Error::BucketAlreadyExists
|
37
|
+
# exception if the bucket already exists.
|
38
|
+
#
|
39
|
+
# ==== Options
|
40
|
+
# * <tt>:location</tt> - location of the bucket
|
41
|
+
# (<tt>huabei-1</tt> or <tt>huadong-1</tt>)
|
42
|
+
# * Any other options are passed through to Connection#request
|
43
|
+
def save(options = {})
|
44
|
+
if options
|
45
|
+
if options.is_a?(String) && options.strip != ''
|
46
|
+
options = {:location => options.strip}
|
47
|
+
end
|
48
|
+
|
49
|
+
if options.is_a?(Hash) && !options.has_key?(:location)
|
50
|
+
options.merge!(:location => location)
|
51
|
+
end
|
52
|
+
else
|
53
|
+
options = {:location => location}
|
54
|
+
end
|
55
|
+
|
56
|
+
create_bucket_configuration(options)
|
32
57
|
|
33
|
-
# Similar to retrieve, but catches S3::Error::NoSuchBucket
|
34
|
-
# exceptions and returns false instead.
|
35
|
-
def exists?
|
36
|
-
retrieve
|
37
58
|
true
|
38
|
-
rescue Error::NoSuchBucket
|
39
|
-
false
|
40
59
|
end
|
41
60
|
|
42
|
-
# Destroys given bucket. Raises an
|
43
|
-
# exception if the bucket is not empty.
|
44
|
-
# bucket passing true (to force destroy)
|
61
|
+
# Destroys given bucket. Raises an Sndacs::Error::BucketNotEmpty
|
62
|
+
# exception if the bucket is not empty.
|
63
|
+
# You can destroy non-empty bucket passing true (to force destroy)
|
45
64
|
def destroy(force = false)
|
46
65
|
delete_bucket
|
66
|
+
|
47
67
|
true
|
48
68
|
rescue Error::BucketNotEmpty
|
49
69
|
if force
|
50
70
|
objects.destroy_all
|
71
|
+
|
51
72
|
retry
|
52
73
|
else
|
53
74
|
raise
|
54
75
|
end
|
55
76
|
end
|
56
77
|
|
57
|
-
#
|
58
|
-
#
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
# * Any other options are passed through to
|
63
|
-
# Connection#request
|
64
|
-
def save(options = {})
|
65
|
-
options = {:location => options} unless options.is_a?(Hash)
|
66
|
-
create_bucket_configuration(options)
|
78
|
+
# Similar to retrieve, but catches Sndacs::Error::NoSuchBucket
|
79
|
+
# exceptions and returns false instead.
|
80
|
+
def exists?
|
81
|
+
retrieve
|
82
|
+
|
67
83
|
true
|
84
|
+
rescue Error::NoSuchBucket
|
85
|
+
false
|
68
86
|
end
|
69
87
|
|
70
|
-
# Returns true if the name of the bucket can be used like +VHOST+
|
71
|
-
#
|
72
|
-
# be used as +VHOST+ (e.g. <tt>bucket_name.
|
88
|
+
# Returns true if the name of the bucket can be used like +VHOST+ name.
|
89
|
+
# If the bucket contains characters like underscore it can't
|
90
|
+
# be used as +VHOST+ (e.g. <tt>bucket_name.storage.grandcloud.cn</tt>)
|
73
91
|
def vhost?
|
74
|
-
#"#@name.#{
|
92
|
+
#"#@name.#{region_host}" =~ /\A#{URI::REGEXP::PATTERN::HOSTNAME}\Z/
|
75
93
|
false
|
76
94
|
end
|
77
95
|
|
78
96
|
# Returns host name of the bucket according (see #vhost? method)
|
79
|
-
def host
|
80
|
-
vhost? ? "#@name.#{
|
97
|
+
def host(public_accessible = false)
|
98
|
+
vhost? ? "#@name.#{region_host(public_accessible)}" : region_host(public_accessible)
|
81
99
|
end
|
82
100
|
|
83
101
|
# Returns path prefix for non +VHOST+ bucket. Path prefix is used
|
@@ -102,19 +120,26 @@ module Sndacs
|
|
102
120
|
"#<#{self.class}:#{name}>"
|
103
121
|
end
|
104
122
|
|
105
|
-
|
123
|
+
private
|
106
124
|
|
107
125
|
attr_writer :service
|
108
126
|
|
109
|
-
def
|
110
|
-
|
111
|
-
|
127
|
+
def create_bucket_configuration(options = {})
|
128
|
+
location = options[:location].to_s.downcase if options[:location]
|
129
|
+
|
130
|
+
options[:headers] ||= {}
|
131
|
+
if location and location != REGION_DEFAULT
|
132
|
+
options[:headers][:content_type] = "application/xml"
|
133
|
+
options[:body] = "<CreateBucketConfiguration><LocationConstraint>#{location}</LocationConstraint></CreateBucketConfiguration>"
|
134
|
+
end
|
135
|
+
|
136
|
+
bucket_request(:put, options)
|
112
137
|
end
|
113
138
|
|
114
139
|
def list_bucket(options = {})
|
115
140
|
response = bucket_request(:get, :params => options)
|
116
141
|
max_keys = options[:max_keys]
|
117
|
-
objects_attributes =
|
142
|
+
objects_attributes = parse_all_objects_result(response.body)
|
118
143
|
|
119
144
|
# If there are more than 1000 objects S3 truncates listing and
|
120
145
|
# we need to request another listing for the remaining objects.
|
@@ -123,11 +148,12 @@ module Sndacs
|
|
123
148
|
|
124
149
|
if max_keys
|
125
150
|
break if objects_attributes.length >= max_keys
|
151
|
+
|
126
152
|
next_request_options[:max_keys] = max_keys - objects_attributes.length
|
127
153
|
end
|
128
154
|
|
129
155
|
response = bucket_request(:get, :params => options.merge(next_request_options))
|
130
|
-
objects_attributes +=
|
156
|
+
objects_attributes += parse_all_objects_result(response.body)
|
131
157
|
end
|
132
158
|
|
133
159
|
objects_attributes.map { |object_attributes| Object.send(:new, self, object_attributes) }
|
@@ -143,37 +169,59 @@ module Sndacs
|
|
143
169
|
end
|
144
170
|
end
|
145
171
|
|
146
|
-
def
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
options[:body] = "<CreateBucketConfiguration><LocationConstraint>#{location}</LocationConstraint></CreateBucketConfiguration>"
|
151
|
-
options[:headers][:content_type] = "application/xml"
|
152
|
-
end
|
153
|
-
bucket_request(:put, options)
|
172
|
+
def location_constraint
|
173
|
+
response = bucket_request(:get, :params => {:location => nil})
|
174
|
+
|
175
|
+
parse_location_constraint(response.body)
|
154
176
|
end
|
155
177
|
|
156
178
|
def delete_bucket
|
157
179
|
bucket_request(:delete)
|
158
180
|
end
|
159
181
|
|
160
|
-
def initialize(service, name) #:nodoc:
|
182
|
+
def initialize(service, name, location = nil) #:nodoc:
|
161
183
|
self.service = service
|
162
184
|
self.name = name
|
185
|
+
|
186
|
+
unless location
|
187
|
+
begin
|
188
|
+
location = location_constraint
|
189
|
+
rescue
|
190
|
+
location = REGION_DEFAULT
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
self.location = location
|
163
195
|
end
|
164
196
|
|
165
197
|
def name=(name)
|
166
198
|
raise ArgumentError.new("Invalid bucket name: #{name}") unless name_valid?(name)
|
199
|
+
|
167
200
|
@name = name
|
168
201
|
end
|
169
202
|
|
170
|
-
def
|
171
|
-
|
172
|
-
service_request(method, options.merge(:host => host, :path => path))
|
203
|
+
def location=(location)
|
204
|
+
@location = location
|
173
205
|
end
|
174
206
|
|
175
207
|
def name_valid?(name)
|
176
208
|
name =~ /\A[a-z0-9][a-z0-9\._-]{2,254}\Z/i and name !~ /\A#{URI::REGEXP::PATTERN::IPV4ADDR}\Z/
|
177
209
|
end
|
210
|
+
|
211
|
+
def region_host(public_accessible = false)
|
212
|
+
rhost = public_accessible ? Config.content_host : Config.host
|
213
|
+
if @location
|
214
|
+
rhost = (public_accessible ? REGION_CONTENT_HOST : REGION_HOST) % @location
|
215
|
+
end
|
216
|
+
|
217
|
+
rhost
|
218
|
+
end
|
219
|
+
|
220
|
+
def bucket_request(method, options = {})
|
221
|
+
path = "#{path_prefix}#{options[:path]}"
|
222
|
+
|
223
|
+
service_request(method, options.merge(:host => host, :path => path))
|
224
|
+
end
|
178
225
|
end
|
226
|
+
|
179
227
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module Sndacs
|
2
|
+
|
2
3
|
module BucketsExtension
|
3
4
|
# Builds new bucket with given name
|
4
5
|
def build(name)
|
@@ -8,7 +9,10 @@ module Sndacs
|
|
8
9
|
# Finds the bucket with given name
|
9
10
|
def find_first(name)
|
10
11
|
bucket = build(name)
|
12
|
+
|
11
13
|
bucket.retrieve
|
14
|
+
rescue Error::NoSuchBucket, Error::ForbiddenBucket
|
15
|
+
nil
|
12
16
|
end
|
13
17
|
alias :find :find_first
|
14
18
|
|
@@ -23,4 +27,5 @@ module Sndacs
|
|
23
27
|
proxy_target.each { |bucket| bucket.destroy(force) }
|
24
28
|
end
|
25
29
|
end
|
30
|
+
|
26
31
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- encoding: utf-8 -*-
|
3
|
+
|
4
|
+
module Sndacs
|
5
|
+
|
6
|
+
class Config
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :access_key_id
|
10
|
+
attr_accessor :secret_access_key
|
11
|
+
|
12
|
+
attr_accessor :proxy
|
13
|
+
attr_accessor :host
|
14
|
+
attr_accessor :content_host
|
15
|
+
attr_accessor :timeout
|
16
|
+
attr_accessor :use_ssl
|
17
|
+
attr_accessor :chunk_size
|
18
|
+
attr_accessor :debug
|
19
|
+
|
20
|
+
def access_key_id
|
21
|
+
@access_key_id ||= ''
|
22
|
+
end
|
23
|
+
|
24
|
+
def secret_access_key
|
25
|
+
@secret_access_key ||= ''
|
26
|
+
end
|
27
|
+
|
28
|
+
def proxy
|
29
|
+
@proxy ||= nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def host
|
33
|
+
@host ||= 'storage.grandcloud.cn'
|
34
|
+
end
|
35
|
+
|
36
|
+
def content_host
|
37
|
+
@content_host ||= 'storage.sdcloud.cn'
|
38
|
+
end
|
39
|
+
|
40
|
+
def timeout
|
41
|
+
@timeout ||= 60
|
42
|
+
end
|
43
|
+
|
44
|
+
def use_ssl
|
45
|
+
@use_ssl ||= false
|
46
|
+
end
|
47
|
+
|
48
|
+
def chunk_size
|
49
|
+
@chunk_size ||= 1048576
|
50
|
+
end
|
51
|
+
|
52
|
+
def debug
|
53
|
+
@debug ||= false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
data/lib/sndacs/connection.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- encoding: utf-8 -*-
|
3
|
+
|
1
4
|
module Sndacs
|
2
5
|
|
3
|
-
# Class responsible for handling connections to
|
6
|
+
# Class responsible for handling connections to grandcloud hosts
|
4
7
|
class Connection
|
8
|
+
|
5
9
|
include Parser
|
6
10
|
|
7
11
|
attr_accessor :access_key_id, :secret_access_key, :use_ssl, :timeout, :debug, :proxy
|
@@ -24,13 +28,13 @@ module Sndacs
|
|
24
28
|
# * <tt>:chunk_size</tt> - Size of a chunk when streaming
|
25
29
|
# (1048576 (1 MiB) by default)
|
26
30
|
def initialize(options = {})
|
27
|
-
@access_key_id = options.fetch(:access_key_id)
|
28
|
-
@secret_access_key = options.fetch(:secret_access_key)
|
29
|
-
@
|
30
|
-
@
|
31
|
-
@
|
32
|
-
@
|
33
|
-
@
|
31
|
+
@access_key_id = options.fetch(:access_key_id, Config.access_key_id)
|
32
|
+
@secret_access_key = options.fetch(:secret_access_key, Config.secret_access_key)
|
33
|
+
@proxy = options.fetch(:proxy, Config.proxy)
|
34
|
+
@timeout = options.fetch(:timeout, Config.timeout)
|
35
|
+
@use_ssl = options.fetch(:use_ssl, Config.use_ssl)
|
36
|
+
@chunk_size = options.fetch(:chunk_size, Config.chunk_size)
|
37
|
+
@debug = options.fetch(:debug, Config.debug)
|
34
38
|
end
|
35
39
|
|
36
40
|
# Makes request with given HTTP method, sets missing parameters,
|
@@ -43,7 +47,7 @@ module Sndacs
|
|
43
47
|
#
|
44
48
|
# ==== Options:
|
45
49
|
# * <tt>:host</tt> - Hostname to connecto to, defaults
|
46
|
-
# to <tt>
|
50
|
+
# to <tt>storage.grandcloud.cn</tt>
|
47
51
|
# * <tt>:path</tt> - path to send request to (REQUIRED)
|
48
52
|
# * <tt>:body</tt> - Request body, only meaningful for
|
49
53
|
# <tt>:put</tt> request
|
@@ -55,7 +59,7 @@ module Sndacs
|
|
55
59
|
# ==== Returns
|
56
60
|
# Net::HTTPResponse object -- response from the server
|
57
61
|
def request(method, options)
|
58
|
-
host = options.fetch(:host,
|
62
|
+
host = options.fetch(:host, Config.host)
|
59
63
|
path = options.fetch(:path)
|
60
64
|
body = options.fetch(:body, nil)
|
61
65
|
params = options.fetch(:params, {})
|
@@ -67,7 +71,10 @@ module Sndacs
|
|
67
71
|
|
68
72
|
if params
|
69
73
|
params = params.is_a?(String) ? params : self.class.parse_params(params)
|
70
|
-
|
74
|
+
|
75
|
+
if params != ''
|
76
|
+
path << "?#{params}"
|
77
|
+
end
|
71
78
|
end
|
72
79
|
|
73
80
|
request = Request.new(@chunk_size, method.to_s.upcase, !!body, method.to_s.upcase != "HEAD", path)
|
@@ -83,6 +90,7 @@ module Sndacs
|
|
83
90
|
else
|
84
91
|
request.body = body
|
85
92
|
end
|
93
|
+
|
86
94
|
request.content_length = body.respond_to?(:lstat) ? body.stat.size : body.size
|
87
95
|
end
|
88
96
|
|
@@ -105,6 +113,7 @@ module Sndacs
|
|
105
113
|
params.each do |key, value|
|
106
114
|
if interesting_keys.include?(key)
|
107
115
|
parsed_key = key.to_s.gsub("_", "-")
|
116
|
+
|
108
117
|
case value
|
109
118
|
when nil
|
110
119
|
result << parsed_key
|
@@ -113,6 +122,7 @@ module Sndacs
|
|
113
122
|
end
|
114
123
|
end
|
115
124
|
end
|
125
|
+
|
116
126
|
result.join("&")
|
117
127
|
end
|
118
128
|
|
@@ -144,18 +154,21 @@ module Sndacs
|
|
144
154
|
if interesting_keys.include?(key)
|
145
155
|
parsed_key = key.to_s.gsub("_", "-")
|
146
156
|
parsed_value = value
|
157
|
+
|
147
158
|
case value
|
148
159
|
when Range
|
149
160
|
parsed_value = "bytes=#{value.first}-#{value.last}"
|
150
161
|
end
|
162
|
+
|
151
163
|
parsed_headers[parsed_key] = parsed_value
|
152
164
|
end
|
153
165
|
end
|
154
166
|
end
|
167
|
+
|
155
168
|
parsed_headers
|
156
169
|
end
|
157
170
|
|
158
|
-
|
171
|
+
private
|
159
172
|
|
160
173
|
def port
|
161
174
|
use_ssl ? 443 : 80
|
@@ -171,6 +184,7 @@ module Sndacs
|
|
171
184
|
http.use_ssl = @use_ssl
|
172
185
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @use_ssl
|
173
186
|
http.read_timeout = @timeout if @timeout
|
187
|
+
|
174
188
|
http
|
175
189
|
end
|
176
190
|
|
@@ -195,9 +209,17 @@ module Sndacs
|
|
195
209
|
http.request(request)
|
196
210
|
end
|
197
211
|
|
198
|
-
|
212
|
+
case response.code.to_i
|
213
|
+
when 301
|
214
|
+
if response.body
|
215
|
+
doc = Document.new response.body
|
216
|
+
|
217
|
+
send_request(doc.elements["Error"].elements["Endpoint"].text, request, true)
|
218
|
+
end
|
219
|
+
when 307
|
199
220
|
if response.body
|
200
221
|
doc = Document.new response.body
|
222
|
+
|
201
223
|
send_request(doc.elements["Error"].elements["Endpoint"].text, request, true)
|
202
224
|
end
|
203
225
|
else
|
@@ -214,12 +236,15 @@ module Sndacs
|
|
214
236
|
raise Error::ResponseError.new(nil, response)
|
215
237
|
else
|
216
238
|
code, message = parse_error(response.body)
|
239
|
+
|
217
240
|
raise Error::ResponseError.exception(code).new(message, response)
|
218
241
|
end
|
219
242
|
else
|
220
243
|
raise(ConnectionError.new(response, "Unknown response code: #{response.code}"))
|
221
244
|
end
|
245
|
+
|
222
246
|
response
|
223
247
|
end
|
224
248
|
end
|
249
|
+
|
225
250
|
end
|
data/lib/sndacs/exceptions.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Sndacs
|
2
|
+
|
2
3
|
module Error
|
3
4
|
|
4
5
|
# All responses with a code between 300 and 599 that contain an
|
@@ -12,7 +13,7 @@ module Sndacs
|
|
12
13
|
class ResponseError < StandardError
|
13
14
|
attr_reader :response
|
14
15
|
|
15
|
-
# Creates new
|
16
|
+
# Creates new Sndacs::ResponseError.
|
16
17
|
#
|
17
18
|
# ==== Parameters
|
18
19
|
# * <tt>message</tt> - what went wrong
|
@@ -23,7 +24,7 @@ module Sndacs
|
|
23
24
|
end
|
24
25
|
|
25
26
|
# Factory for all other Exception classes in module, each for
|
26
|
-
# every error response available from
|
27
|
+
# every error response available from SNDA Cloud Storage
|
27
28
|
#
|
28
29
|
# ==== Parameters
|
29
30
|
# * <tt>code</tt> - Code name of exception
|
@@ -32,7 +33,7 @@ module Sndacs
|
|
32
33
|
# Descendant of ResponseError suitable for that exception code
|
33
34
|
# or ResponseError class if no class found
|
34
35
|
def self.exception(code)
|
35
|
-
|
36
|
+
Sndacs::Error.const_get(code)
|
36
37
|
rescue NameError
|
37
38
|
ResponseError
|
38
39
|
end
|
@@ -52,6 +53,7 @@ module Sndacs
|
|
52
53
|
class EntityTooSmall < ResponseError; end
|
53
54
|
class EntityTooLarge < ResponseError; end
|
54
55
|
class ExpiredToken < ResponseError; end
|
56
|
+
class ForbiddenBucket < ResponseError; end
|
55
57
|
class IncompleteBody < ResponseError; end
|
56
58
|
class IncorrectNumberOfFilesInPostRequestPOST < ResponseError; end
|
57
59
|
class InlineDataTooLarge < ResponseError; end
|
@@ -107,4 +109,5 @@ module Sndacs
|
|
107
109
|
class UnresolvableGrantByEmailAddress < ResponseError; end
|
108
110
|
class UserKeyMustBeSpecified < ResponseError; end
|
109
111
|
end
|
112
|
+
|
110
113
|
end
|