swift_client 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/swift_client/version.rb +1 -1
- data/lib/swift_client.rb +52 -34
- data/test/swift_client_test.rb +18 -1
- metadata +1 -1
data/lib/swift_client/version.rb
CHANGED
data/lib/swift_client.rb
CHANGED
@@ -3,11 +3,13 @@ require "swift_client/version"
|
|
3
3
|
|
4
4
|
require "httparty"
|
5
5
|
require "mime-types"
|
6
|
+
require "openssl"
|
6
7
|
|
7
8
|
class SwiftClient
|
8
9
|
class AuthenticationError < StandardError; end
|
9
10
|
class OptionError < StandardError; end
|
10
11
|
class EmptyNameError < StandardError; end
|
12
|
+
class TempUrlKeyMissing < StandardError; end
|
11
13
|
|
12
14
|
class ResponseError < StandardError
|
13
15
|
attr_accessor :code, :message
|
@@ -38,69 +40,69 @@ class SwiftClient
|
|
38
40
|
request :get, "/", :query => query
|
39
41
|
end
|
40
42
|
|
41
|
-
def get_container(
|
42
|
-
raise(EmptyNameError) if
|
43
|
+
def get_container(container, query = {})
|
44
|
+
raise(EmptyNameError) if container.empty?
|
43
45
|
|
44
|
-
request :get, "/#{
|
46
|
+
request :get, "/#{container}", :query => query
|
45
47
|
end
|
46
48
|
|
47
|
-
def head_container(
|
48
|
-
raise(EmptyNameError) if
|
49
|
+
def head_container(container)
|
50
|
+
raise(EmptyNameError) if container.empty?
|
49
51
|
|
50
|
-
request :head, "/#{
|
52
|
+
request :head, "/#{container}"
|
51
53
|
end
|
52
54
|
|
53
|
-
def put_container(
|
54
|
-
raise(EmptyNameError) if
|
55
|
+
def put_container(container, headers = {})
|
56
|
+
raise(EmptyNameError) if container.empty?
|
55
57
|
|
56
|
-
request :put, "/#{
|
58
|
+
request :put, "/#{container}", :headers => headers
|
57
59
|
end
|
58
60
|
|
59
|
-
def post_container(
|
60
|
-
raise(EmptyNameError) if
|
61
|
+
def post_container(container, headers = {})
|
62
|
+
raise(EmptyNameError) if container.empty?
|
61
63
|
|
62
|
-
request :post, "/#{
|
64
|
+
request :post, "/#{container}", :headers => headers
|
63
65
|
end
|
64
66
|
|
65
|
-
def delete_container(
|
66
|
-
raise(EmptyNameError) if
|
67
|
+
def delete_container(container)
|
68
|
+
raise(EmptyNameError) if container.empty?
|
67
69
|
|
68
|
-
request :delete, "/#{
|
70
|
+
request :delete, "/#{container}"
|
69
71
|
end
|
70
72
|
|
71
|
-
def put_object(
|
72
|
-
raise(EmptyNameError) if
|
73
|
+
def put_object(object, data_or_io, container, headers = {})
|
74
|
+
raise(EmptyNameError) if object.empty? || container.empty?
|
73
75
|
|
74
|
-
mime_type = MIME::Types.of(
|
76
|
+
mime_type = MIME::Types.of(object).first
|
75
77
|
|
76
78
|
extended_headers = headers.dup
|
77
79
|
extended_headers["Content-Type"] ||= mime_type.content_type if mime_type
|
78
80
|
|
79
|
-
request :put, "/#{container}/#{
|
81
|
+
request :put, "/#{container}/#{object}", :body => data_or_io.respond_to?(:read) ? data_or_io.read : data_or_io, :headers => extended_headers
|
80
82
|
end
|
81
83
|
|
82
|
-
def post_object(
|
83
|
-
raise(EmptyNameError) if
|
84
|
+
def post_object(object, container, headers = {})
|
85
|
+
raise(EmptyNameError) if object.empty? || container.empty?
|
84
86
|
|
85
|
-
request :post, "/#{container}/#{
|
87
|
+
request :post, "/#{container}/#{object}", :headers => headers
|
86
88
|
end
|
87
89
|
|
88
|
-
def get_object(
|
89
|
-
raise(EmptyNameError) if
|
90
|
+
def get_object(object, container)
|
91
|
+
raise(EmptyNameError) if object.empty? || container.empty?
|
90
92
|
|
91
|
-
request :get, "/#{container}/#{
|
93
|
+
request :get, "/#{container}/#{object}"
|
92
94
|
end
|
93
95
|
|
94
|
-
def head_object(
|
95
|
-
raise(EmptyNameError) if
|
96
|
+
def head_object(object, container)
|
97
|
+
raise(EmptyNameError) if object.empty? || container.empty?
|
96
98
|
|
97
|
-
request :head, "/#{container}/#{
|
99
|
+
request :head, "/#{container}/#{object}"
|
98
100
|
end
|
99
101
|
|
100
|
-
def delete_object(
|
101
|
-
raise(EmptyNameError) if
|
102
|
+
def delete_object(object, container)
|
103
|
+
raise(EmptyNameError) if object.empty? || container.empty?
|
102
104
|
|
103
|
-
request :delete, "/#{container}/#{
|
105
|
+
request :delete, "/#{container}/#{object}"
|
104
106
|
end
|
105
107
|
|
106
108
|
def get_objects(container, query = {})
|
@@ -109,6 +111,24 @@ class SwiftClient
|
|
109
111
|
request :get, "/#{container}", :query => query
|
110
112
|
end
|
111
113
|
|
114
|
+
def public_url(object, container)
|
115
|
+
raise(EmptyNameError) if object.empty? || container.empty?
|
116
|
+
|
117
|
+
"#{storage_url}/#{container}/#{object}"
|
118
|
+
end
|
119
|
+
|
120
|
+
def temp_url(object, container, opts = {})
|
121
|
+
raise(EmptyNameError) if object.empty? || container.empty?
|
122
|
+
raise(TempUrlKeyMissing) unless options[:temp_url_key]
|
123
|
+
|
124
|
+
expires = (Time.now + (options[:expires_in] || 3600).to_i).to_i
|
125
|
+
path = "/#{container}/#{object}"
|
126
|
+
|
127
|
+
signature = OpenSSL::HMAC.hexdigest("sha1", options[:temp_url_key], "GET\n#{expires}\n#{path}")
|
128
|
+
|
129
|
+
"#{storage_url}#{path}?temp_url_sig=#{signature}&temp_url_expires=#{expires}"
|
130
|
+
end
|
131
|
+
|
112
132
|
private
|
113
133
|
|
114
134
|
def request(method, path, opts = {})
|
@@ -135,9 +155,7 @@ class SwiftClient
|
|
135
155
|
raise(AuthenticationError, "#{response.code}: #{response.message}") unless response.success?
|
136
156
|
|
137
157
|
self.auth_token = response.headers["X-Auth-Token"]
|
138
|
-
self.storage_url = response.headers["X-Storage-Url"]
|
139
|
-
|
140
|
-
storage_url.gsub!(/^http:/, "https:") if options[:auth_url] =~ /^https:/
|
158
|
+
self.storage_url = options[:storage_url] || response.headers["X-Storage-Url"]
|
141
159
|
end
|
142
160
|
end
|
143
161
|
|
data/test/swift_client_test.rb
CHANGED
@@ -5,12 +5,21 @@ class SwiftClientTest < MiniTest::Test
|
|
5
5
|
def setup
|
6
6
|
stub_request(:get, "https://example.com/auth/v1.0").with(:headers => { "X-Auth-Key" => "secret", "X-Auth-User" => "account:username" }).to_return(:status => 200, :body => "", :headers => { "X-Auth-Token" => "Token", "X-Storage-Url" => "https://example.com/v1/AUTH_account" })
|
7
7
|
|
8
|
-
@swift_client = SwiftClient.new(:auth_url => "https://example.com/auth/v1.0", :username => "account:username", :api_key => "secret")
|
8
|
+
@swift_client = SwiftClient.new(:auth_url => "https://example.com/auth/v1.0", :username => "account:username", :api_key => "secret", :temp_url_key => "Temp url key")
|
9
9
|
|
10
10
|
assert_equal "Token", @swift_client.auth_token
|
11
11
|
assert_equal "https://example.com/v1/AUTH_account", @swift_client.storage_url
|
12
12
|
end
|
13
13
|
|
14
|
+
def test_storage_url
|
15
|
+
stub_request(:get, "https://example.com/auth/v1.0").with(:headers => { "X-Auth-Key" => "secret", "X-Auth-User" => "account:username" }).to_return(:status => 200, :body => "", :headers => { "X-Auth-Token" => "Token", "X-Storage-Url" => "https://example.com/v1/AUTH_account" })
|
16
|
+
|
17
|
+
@swift_client = SwiftClient.new(:auth_url => "https://example.com/auth/v1.0", :username => "account:username", :api_key => "secret", :storage_url => "https://storage-url.com/path")
|
18
|
+
|
19
|
+
assert_equal "Token", @swift_client.auth_token
|
20
|
+
assert_equal "https://storage-url.com/path", @swift_client.storage_url
|
21
|
+
end
|
22
|
+
|
14
23
|
def test_get_containers
|
15
24
|
containers = [
|
16
25
|
{ "count" => 1, "bytes" => 1, "name" => "container-1" },
|
@@ -114,5 +123,13 @@ class SwiftClientTest < MiniTest::Test
|
|
114
123
|
assert_equal "Not Found", e.message
|
115
124
|
end
|
116
125
|
end
|
126
|
+
|
127
|
+
def test_public_url
|
128
|
+
assert_equal "https://example.com/v1/AUTH_account/container/object", @swift_client.public_url("object", "container")
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_temp_url
|
132
|
+
assert @swift_client.temp_url("object", "container", :expires_in => 3600) =~ %r{https://example.com/v1/AUTH_account/container/object\?temp_url_sig=[a-f0-9]{40}&temp_url_expires=[0-9]+}
|
133
|
+
end
|
117
134
|
end
|
118
135
|
|