gstore 0.1.0 → 0.2.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.
@@ -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. Example
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
@@ -1,5 +1,5 @@
1
1
  require 'gstore/client'
2
2
 
3
3
  module GStore
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
@@ -14,26 +14,30 @@ module GStore
14
14
 
15
15
  private
16
16
 
17
- def get(bucket, path, params={}, options={})
18
- _http_request(Net::HTTP::Get, bucket, path, params, options)
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, params={}, options={})
22
- _http_request(Net::HTTP::Put, bucket, path, params, options)
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, params={}, options={})
26
- _http_request(Net::HTTP::Delete, bucket, path, params, options)
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, params={}, options={})
30
- _http_request(Net::HTTP::Head, bucket, path, params, options)
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, params, options={})
33
+ def _http_request(method, bucket, path, options={})
34
34
  host = @host
35
35
  host = "#{bucket}.#{@host}" if bucket
36
- signed_request(method, host, path, params, options)
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
@@ -1,7 +1,7 @@
1
1
  module GStore
2
2
  class Client
3
- def put_object(bucket, filename, data, options={})
4
- put(bucket, "/#{filename}", options, data)
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={})
@@ -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.1.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-15 00:00:00 +01:00
12
+ date: 2010-06-16 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15