gstore 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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) Richard Taylor
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,53 @@
1
+ h1. Ruby client library for the Google Storage API
2
+
3
+ This is the first release and supports all the basic operations. Advanced support for ACLs etc.. coming soon
4
+
5
+ h2. Install the gem
6
+
7
+ sudo gem install gstore
8
+
9
+ h2. Using the gem
10
+
11
+ Visit "The Google Storage Key Manager":https://sandbox.google.com/storage/m/manage to get your access and secret keys.
12
+
13
+ In your code just: <code>require 'gstore'</code>
14
+
15
+ h2. Example
16
+
17
+ Create an instance of the client with your credentials:
18
+
19
+ <pre><code>client = GStore::Client.new(
20
+ :access_key => 'YOUR_ACCESS_KEY',
21
+ :secret_key => 'YOUR_SECRET_KEY'
22
+ )
23
+
24
+ # List all of your existing Buckets
25
+ client.list_buckets
26
+ </code></pre>
27
+
28
+ Here are some example bucket operations:
29
+
30
+ <pre><code># Create a Bucket
31
+ client.create_bucket('my_unique_bucket')
32
+
33
+ # Retrieve a Bucket
34
+ client.get_bucket('my_unique_bucket')
35
+
36
+ # Delete a [empty] Bucket
37
+ client.delete_bucket('my_unique_bucket')
38
+ </code></pre>
39
+
40
+ Once you have a bucket you can manipulate objects in the following way:
41
+
42
+ <pre><code># Store a file in a bucket
43
+ client.put_object('my_unique_bucket', 'my_first_object', :data => File.read('mytext.txt'))
44
+
45
+ # Retrieve the contents of the object in the specified bucket
46
+ puts client.get_object('my_unique_bucket', 'my_first_object')
47
+
48
+ # Alternatively specify an outfile and the contents will be saved to there
49
+ client.get_object('my_unique_bucket', 'my_first_object', :outfile => 'retrieved_mytext.txt')
50
+
51
+ # Delete an object from the bucket
52
+ client.delete_object('my_unique_bucket', 'my_first_object')
53
+ </code></pre>
@@ -0,0 +1,5 @@
1
+ require 'gstore/client'
2
+
3
+ module GStore
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,21 @@
1
+ module GStore
2
+ class Client
3
+
4
+ def list_buckets(options={})
5
+ get(nil, '/', options)
6
+ end
7
+
8
+ def create_bucket(bucket, options={})
9
+ put(bucket, '/', options)
10
+ end
11
+
12
+ def get_bucket(bucket, options={})
13
+ get(bucket, '/', options)
14
+ end
15
+
16
+ def delete_bucket(bucket, options={})
17
+ delete(bucket, '/', options)
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,41 @@
1
+ require 'gstore/request'
2
+ require 'gstore/bucket'
3
+ require 'gstore/object'
4
+
5
+ module GStore
6
+ class Client
7
+
8
+ def initialize(options = {})
9
+ @access_key = options[:access_key]
10
+ @secret_key = options[:secret_key]
11
+ @debug = options[:debug] and options[:debug] == true
12
+ @host = options[:host] || 'commondatastorage.googleapis.com'
13
+ end
14
+
15
+ private
16
+
17
+ def get(bucket, path, params={}, options={})
18
+ _http_request(Net::HTTP::Get, bucket, path, params, options)
19
+ end
20
+
21
+ def put(bucket, path, params={}, options={})
22
+ _http_request(Net::HTTP::Put, bucket, path, params, options)
23
+ end
24
+
25
+ def delete(bucket, path, params={}, options={})
26
+ _http_request(Net::HTTP::Delete, bucket, path, params, options)
27
+ end
28
+
29
+ def head(bucket, path, params={}, options={})
30
+ _http_request(Net::HTTP::Head, bucket, path, params, options)
31
+ end
32
+
33
+ def _http_request(method, bucket, path, params, options={})
34
+ host = @host
35
+ host = "#{bucket}.#{@host}" if bucket
36
+ signed_request(method, host, path, params, options)
37
+ end
38
+
39
+ end
40
+ end
41
+
@@ -0,0 +1,25 @@
1
+ module GStore
2
+ class Client
3
+ def put_object(bucket, filename, data, options={})
4
+ put(bucket, "/#{filename}", options, data)
5
+ end
6
+
7
+ def get_object(bucket, filename, options={})
8
+ outfile = options.delete(:outfile)
9
+ res = get(bucket, "/#{filename}", options)
10
+ if outfile
11
+ File.open(outfile, 'w') {|f| f.write(res) }
12
+ else
13
+ res
14
+ end
15
+ end
16
+
17
+ def delete_object(bucket, filename, options={})
18
+ delete(bucket, "/#{filename}", options)
19
+ end
20
+
21
+ def get_object_metadata(bucket, filename, options={})
22
+ head(bucket, "/#{filename}", options)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,98 @@
1
+ require 'time'
2
+ require 'openssl'
3
+ require 'digest/sha1'
4
+ require 'base64'
5
+ require 'uri'
6
+ require 'net/https'
7
+ require 'cgi'
8
+
9
+ module GStore
10
+ class Client
11
+
12
+ def signed_request(method, host, path, params={}, options={})
13
+
14
+ if @debug
15
+ puts
16
+ puts "***** METHOD: #{method}"
17
+ puts "***** HOST: #{host}"
18
+ puts "***** PATH: #{path}"
19
+ puts "***** PARAMS: #{params.inspect}"
20
+ puts "***** OPTIONS: #{options.inspect}"
21
+ puts
22
+ end
23
+
24
+ headers = {
25
+ :Host => host,
26
+ :Date => Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S -0000'),
27
+ :"Content-Type" => 'text/plain',
28
+ #:"Content-MD5" => ''
29
+ }
30
+ if options[:data]
31
+ headers = headers.merge(:"Content-Length" => options[:data].size)
32
+ else
33
+ headers = headers.merge(:"Content-Length" => 0)
34
+ end
35
+
36
+ bucket = nil
37
+ if host =~ /(\S+).#{@host}/
38
+ bucket = $1
39
+ end
40
+
41
+ canonical_headers = method.name.gsub('Net::HTTP::', '').upcase + "\n" +
42
+ '' + "\n" + # Content-MD5
43
+ headers[:"Content-Type"] + "\n" + # Content-Type
44
+ headers[:Date] + "\n" # Date
45
+
46
+ canonical_resource = ""
47
+ canonical_resource += "/#{bucket}" if bucket
48
+ canonical_resource += path
49
+
50
+ authorization = 'GOOG1 ' + @access_key + ':' + sign((canonical_headers + canonical_resource).toutf8)
51
+
52
+ if @debug
53
+ puts
54
+ puts "+++++ BUCKET: #{bucket}"
55
+ puts "+++++ HEADERS: #{headers.inspect}"
56
+ puts "+++++ CANONICAL_HEADERS: #{canonical_headers}"
57
+ puts "+++++ CANONICAL_RESOURCE: #{canonical_resource}"
58
+ puts "+++++ AUTHORIZATION: #{authorization}"
59
+ puts
60
+ end
61
+
62
+ _http_do(method, host, path, params_to_request_string(params), headers.merge(:Authorization => authorization), options[:data])
63
+ end
64
+
65
+ private
66
+ def sign(str)
67
+ digest = OpenSSL::Digest::Digest.new('sha1')
68
+ b64_hmac = Base64.encode64(OpenSSL::HMAC.digest(digest, @secret_key, str)).gsub("\n","")
69
+ end
70
+
71
+ def _http_do(method, host, path, params, headers, data=nil)
72
+ http = Net::HTTP.new(host, 443)
73
+ http.use_ssl = true
74
+
75
+ http.start do
76
+ req = method.new(path)
77
+ req.content_type = 'application/x-www-form-urlencoded'
78
+ req['User-Agent'] = "moomerman-gstore-gem"
79
+ headers.each do |key, value|
80
+ req[key.to_s] = value
81
+ end
82
+
83
+ response = http.request(req, data)
84
+
85
+ return response.body
86
+ end
87
+ end
88
+
89
+ def params_to_request_string(params)
90
+ sorted_params = params.sort {|x,y| x[0].to_s <=> y[0].to_s}
91
+ escaped_params = sorted_params.collect do |p|
92
+ encoded = (CGI::escape(p[0].to_s) + "=" + CGI::escape(p[1].to_s))
93
+ encoded.gsub('+', '%20')
94
+ end
95
+ escaped_params.join('&')
96
+ end
97
+ end
98
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gstore
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Richard Taylor
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-06-15 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: gstore is a Ruby client library for the Google Storage API.
17
+ email: moomerman@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - LICENSE
26
+ - README.textile
27
+ - lib/gstore.rb
28
+ - lib/gstore/bucket.rb
29
+ - lib/gstore/client.rb
30
+ - lib/gstore/object.rb
31
+ - lib/gstore/request.rb
32
+ has_rdoc: true
33
+ homepage: http://github.com/moomerman/gstore
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --inline-source
39
+ - --charset=UTF-8
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project: gstore
57
+ rubygems_version: 1.3.5
58
+ signing_key:
59
+ specification_version: 2
60
+ summary: gstore is a Ruby client library for the Google Storage API.
61
+ test_files: []
62
+