gstore 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +31 -2
- data/lib/gstore.rb +1 -1
- data/lib/gstore/client.rb +14 -10
- data/lib/gstore/object.rb +2 -2
- data/lib/gstore/request.rb +20 -8
- metadata +2 -2
data/README.textile
CHANGED
@@ -12,7 +12,7 @@ Visit "The Google Storage Key Manager":https://sandbox.google.com/storage/m/mana
|
|
12
12
|
|
13
13
|
In your code just: <code>require 'gstore'</code>
|
14
14
|
|
15
|
-
h2.
|
15
|
+
h2. Basic Examples
|
16
16
|
|
17
17
|
Create an instance of the client with your credentials:
|
18
18
|
|
@@ -50,4 +50,33 @@ client.get_object('my_unique_bucket', 'my_first_object', :outfile => 'retrieved_
|
|
50
50
|
|
51
51
|
# Delete an object from the bucket
|
52
52
|
client.delete_object('my_unique_bucket', 'my_first_object')
|
53
|
-
</code></pre>
|
53
|
+
</code></pre>
|
54
|
+
|
55
|
+
h2. Advanced Examples
|
56
|
+
|
57
|
+
h3. Query parameters
|
58
|
+
|
59
|
+
For certain requests like <code>get_bucket('my_unique_bucket')</code> you can specify query parameters like <code>max-keys</code>, <code>prefix</code>, <code>delimiter</code> and <code>marker</code> (see "The Google Developer Guide":http://code.google.com/apis/storage/docs/developer-guide.html) for more information.
|
60
|
+
|
61
|
+
Here's an example with gstore:
|
62
|
+
|
63
|
+
<pre><code>client.get_bucket('my_unique_bucket', :params => {:max_keys => 2, :prefix => 'backup'})
|
64
|
+
</code></pre>
|
65
|
+
|
66
|
+
* <code>max_keys</code> is converted to <code>max-keys</code> so you can use the ruby symbol without quotes. <code>:"max-keys"</code> and <code>"max-keys"</code> also work
|
67
|
+
|
68
|
+
h3. Access Control
|
69
|
+
|
70
|
+
Here is how you retrieve the ACL for a bucket or object:
|
71
|
+
|
72
|
+
<pre><code>client.get_bucket('my_unique_bucket', :params => {:acl => ''})
|
73
|
+
client.get_bucket('my_unique_bucket', 'my_first_object', :params => {:acl => ''})
|
74
|
+
</pre></code>
|
75
|
+
|
76
|
+
To create a bucket or object with one of the pre-defined ACL's:
|
77
|
+
|
78
|
+
<pre><code>client.create_bucket('my_public_bucket', :headers => {:x_goog_acl => 'public-read'})
|
79
|
+
client.create_object('my_public_bucket', 'my_public_object', :headers => {:x_goog_acl => 'public-read-write'})
|
80
|
+
</code></pre>
|
81
|
+
|
82
|
+
* <code>x_goog_acl</code> is converted to <code>x-goog-acl</code> so you can use the ruby symbol without quotes. <code>:"x-goog-acl"</code> and <code>"x-goog-acl"</code> also work
|
data/lib/gstore.rb
CHANGED
data/lib/gstore/client.rb
CHANGED
@@ -14,26 +14,30 @@ module GStore
|
|
14
14
|
|
15
15
|
private
|
16
16
|
|
17
|
-
def get(bucket, path,
|
18
|
-
_http_request(Net::HTTP::Get, bucket, path,
|
17
|
+
def get(bucket, path, options={})
|
18
|
+
_http_request(Net::HTTP::Get, bucket, path, options)
|
19
19
|
end
|
20
20
|
|
21
|
-
def put(bucket, path,
|
22
|
-
_http_request(Net::HTTP::Put, bucket, path,
|
21
|
+
def put(bucket, path, options={})
|
22
|
+
_http_request(Net::HTTP::Put, bucket, path, options)
|
23
23
|
end
|
24
24
|
|
25
|
-
def delete(bucket, path,
|
26
|
-
_http_request(Net::HTTP::Delete, bucket, path,
|
25
|
+
def delete(bucket, path, options={})
|
26
|
+
_http_request(Net::HTTP::Delete, bucket, path, options)
|
27
27
|
end
|
28
28
|
|
29
|
-
def head(bucket, path,
|
30
|
-
_http_request(Net::HTTP::Head, bucket, path,
|
29
|
+
def head(bucket, path, options={})
|
30
|
+
_http_request(Net::HTTP::Head, bucket, path, options)
|
31
31
|
end
|
32
32
|
|
33
|
-
def _http_request(method, bucket, path,
|
33
|
+
def _http_request(method, bucket, path, options={})
|
34
34
|
host = @host
|
35
35
|
host = "#{bucket}.#{@host}" if bucket
|
36
|
-
|
36
|
+
params = options.delete(:params) || {}
|
37
|
+
headers = options.delete(:headers) || {}
|
38
|
+
params[:"max-keys"] = params.delete(:max_keys) if params and params[:max_keys]
|
39
|
+
headers[:"x-goog-acl"] = headers.delete(:x_goog_acl) if headers and headers[:x_goog_acl]
|
40
|
+
signed_request(method, host, path, params, headers, options)
|
37
41
|
end
|
38
42
|
|
39
43
|
end
|
data/lib/gstore/object.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module GStore
|
2
2
|
class Client
|
3
|
-
def put_object(bucket, filename,
|
4
|
-
put(bucket, "/#{filename}", options
|
3
|
+
def put_object(bucket, filename, options={})
|
4
|
+
put(bucket, "/#{filename}", options)
|
5
5
|
end
|
6
6
|
|
7
7
|
def get_object(bucket, filename, options={})
|
data/lib/gstore/request.rb
CHANGED
@@ -9,7 +9,7 @@ require 'cgi'
|
|
9
9
|
module GStore
|
10
10
|
class Client
|
11
11
|
|
12
|
-
def signed_request(method, host, path, params={}, options={})
|
12
|
+
def signed_request(method, host, path, params={}, headers={}, options={})
|
13
13
|
|
14
14
|
if @debug
|
15
15
|
puts
|
@@ -17,21 +17,24 @@ module GStore
|
|
17
17
|
puts "***** HOST: #{host}"
|
18
18
|
puts "***** PATH: #{path}"
|
19
19
|
puts "***** PARAMS: #{params.inspect}"
|
20
|
+
puts "***** HEADERS: #{headers.inspect}"
|
20
21
|
puts "***** OPTIONS: #{options.inspect}"
|
21
22
|
puts
|
22
23
|
end
|
23
24
|
|
24
|
-
headers
|
25
|
+
headers.merge!({
|
25
26
|
:Host => host,
|
26
|
-
:Date => Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S -0000')
|
27
|
-
:"Content-Type" => 'text/plain',
|
27
|
+
:Date => Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S -0000')
|
28
28
|
#:"Content-MD5" => ''
|
29
|
-
}
|
29
|
+
})
|
30
|
+
|
30
31
|
if options[:data]
|
31
32
|
headers = headers.merge(:"Content-Length" => options[:data].size)
|
32
33
|
else
|
33
34
|
headers = headers.merge(:"Content-Length" => 0)
|
34
35
|
end
|
36
|
+
headers[:"Content-Type"] ||= 'text/plain'
|
37
|
+
|
35
38
|
|
36
39
|
bucket = nil
|
37
40
|
if host =~ /(\S+).#{@host}/
|
@@ -42,10 +45,16 @@ module GStore
|
|
42
45
|
'' + "\n" + # Content-MD5
|
43
46
|
headers[:"Content-Type"] + "\n" + # Content-Type
|
44
47
|
headers[:Date] + "\n" # Date
|
48
|
+
headers.each do |key,value|
|
49
|
+
if key.to_s =~ /^x-goog/
|
50
|
+
canonical_headers += "#{key}:#{value}\n"
|
51
|
+
end
|
52
|
+
end
|
45
53
|
|
46
54
|
canonical_resource = ""
|
47
55
|
canonical_resource += "/#{bucket}" if bucket
|
48
56
|
canonical_resource += path
|
57
|
+
canonical_resource += '?acl' if params[:acl]
|
49
58
|
|
50
59
|
authorization = 'GOOG1 ' + @access_key + ':' + sign((canonical_headers + canonical_resource).toutf8)
|
51
60
|
|
@@ -71,15 +80,17 @@ module GStore
|
|
71
80
|
def _http_do(method, host, path, params, headers, data=nil)
|
72
81
|
http = Net::HTTP.new(host, 443)
|
73
82
|
http.use_ssl = true
|
83
|
+
http.set_debug_output $stderr if @debug
|
84
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
74
85
|
|
75
86
|
http.start do
|
76
|
-
req = method.new(path)
|
87
|
+
req = method.new(path + params)
|
77
88
|
req.content_type = 'application/x-www-form-urlencoded'
|
78
89
|
req['User-Agent'] = "moomerman-gstore-gem"
|
79
90
|
headers.each do |key, value|
|
80
91
|
req[key.to_s] = value
|
81
92
|
end
|
82
|
-
|
93
|
+
|
83
94
|
response = http.request(req, data)
|
84
95
|
|
85
96
|
return response.body
|
@@ -87,12 +98,13 @@ module GStore
|
|
87
98
|
end
|
88
99
|
|
89
100
|
def params_to_request_string(params)
|
101
|
+
return "" if params.empty?
|
90
102
|
sorted_params = params.sort {|x,y| x[0].to_s <=> y[0].to_s}
|
91
103
|
escaped_params = sorted_params.collect do |p|
|
92
104
|
encoded = (CGI::escape(p[0].to_s) + "=" + CGI::escape(p[1].to_s))
|
93
105
|
encoded.gsub('+', '%20')
|
94
106
|
end
|
95
|
-
escaped_params.join('&')
|
107
|
+
"?#{escaped_params.join('&')}"
|
96
108
|
end
|
97
109
|
end
|
98
110
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gstore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Taylor
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-06-
|
12
|
+
date: 2010-06-16 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|