google_storage 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,61 +1,86 @@
1
1
  h1. Google Storage using API v2
2
2
 
3
- I wrote this gem because the only google storage gems I could find already written were either written a while ago and only set up to use the original
4
- version of Google's API or they were dependent on Gems that don't run properly on... dare I say it... windows.. :) Apologies, I'm without choice
5
- at the moment, but anyways, this gem should run fine on all platforms and I've tried to keep dependencies to a minimum. Let me know if you find
6
- any bugs though ok and feel free to contribute.
3
+ *last updated 30/9/2012*
7
4
 
8
- h2. Response Object
5
+ I wrote this gem to work with the newer v2 of the Google Storage API. It will run fine on all platforms and has been tested to work
6
+ with ruby 1.8.7 and above. Let me know if you find any bugs though and feel free to make contributions.
9
7
 
10
- A lot of the responses from GS on the backend are a little bit inconsistent, sometimes returning response codes, sometimes returning heavily
11
- nested xml data and sometimes just returning information in the response header. I've tried to parse all responses that are returned from GS into a fairly
12
- consistent type of response Hash object. Usually this is in the form of something like this:
8
+ h2. Setup Guide
13
9
 
14
- <pre>
15
- #successful responses will always include a :success => true key/value pair
10
+ This guide assumes you've already set up a Google Storage account through Google, if you haven't already yet, read the
11
+ 'Setup your Google Project Client ID's' section further below and create one first before trying to setup this gem.
16
12
 
17
- client.list_buckets
18
- => {:success=>true,
19
- :buckets=>[ {"Name"=>"bucket_1_example", "CreationDate"=>"2011-06-07T07:11:18.480Z"},
20
- {"Name"=>"bucket_2_example", "CreationDate"=>"2011-05-31T10:58:08.097Z"},
21
- {"Name"=>"bucket_3_example", "CreationDate"=>"2011-06-06T22:47:10.728Z"}],
22
- :raw=>{ THIS :raw FIELD WILL RETURN A HASH OF THE UNPARSED RESPONSE IN CASE YOU NEED IT }
23
- }
13
+ There's a couple of steps to follow in order to setup this gem. The new Google Storage APIv2 uses OAuth 2.0 to authenticate requests,
14
+ you can read up on the nitty gritty details if you like, here:
15
+ "Google's OAuth2 Guide":http://code.google.com/apis/accounts/docs/OAuth2.html
24
16
 
25
- #Unsuccessful responses will return an "Error" Hash
17
+ I'll try and add client side support also once this gem is up and running properly, but for the moment it's only setup to support
18
+ server side applications.
26
19
 
27
- client.get_bucket("bucket_4_example")
28
- => {"Error"=>{
29
- "Code"=>"NoSuchBucket",
30
- "Message"=>"The specified bucket does not exist."
31
- }}
20
+ But it's also possible to run this gem from the command line, or through a plain ruby script if you want.
21
+
22
+
23
+ h3. Rails setup
24
+
25
+ <pre>#Include the google_storage gem in your Gemfile and install config files
26
+ gem 'google_storage'
27
+ bundle install
28
+
29
+ #Then in your Rails application directory run:
30
+ cd /rails_app
31
+ rails generate google_storage:install
32
+
33
+ #This will generate some rake tasks and a google_storage.yml file in your config directory.
34
+ /rails_app/config/google_storage.yml
35
+ /rails_app/lib/tasks/google_storage.task
36
+
37
+ #Before running any of the rake tasks, update the google_storage.yml file with your own Google Storage login details
38
+ #and read the commented out code in the google_storage.yml on how to use the rake tasks to acquire a refresh token
39
+ #from google
32
40
  </pre>
33
41
 
34
- h2. Setup Guide
42
+ h3. Ruby setup
35
43
 
36
- There's a couple of steps to follow in order to setup this gem. The new Google Storage APIv2 uses OAuth 2.0 to authenticate requests, you can read up
37
- more on the nitty gritty if you like here: "Google's OAuth2 Guide":http://code.google.com/apis/accounts/docs/OAuth2.html
44
+ <pre>#Install the google_storage gem first
38
45
 
39
- I'll try and add client side support also once this gem is up and running properly, but for the moment it's only setup to support server side web
40
- applications.
46
+ gem install google_storage
41
47
 
42
- But it's also possible to run this gem from the command line if you want.
48
+ #From the command line run: 'deploy_gs_yml' to generate a google_storage.yml file
43
49
 
50
+ cd /tmp
51
+ deploy_gs_yml
44
52
 
45
- h2. Install the google_storage Gem
53
+ #This will generate a template file: /tmp/google_storage.yml
46
54
 
47
- Include the google_storage gem in your Gemfile and install config files
48
- <pre>gem 'google_storage'
49
- bundle install
50
- </pre>
51
- Then in your Rails application directory run:
52
- <pre>rails generate google_storage:install
53
- </pre>
54
- This will generate some rake tasks a google_storage.yml file in your config directory.
55
- <pre>/Application/config/google_storage.yml
56
- /Application/lib/tasks/google_storage.task
57
- </pre>
55
+ #Open the generated google_storage.yml file and enter your own google credentials
56
+ #Then run IRB and type the following:
58
57
 
58
+ require 'google_storage'
59
+ client = GoogleStorage::Client.new(:config_yml => '/tmp/google_storage.yml')
60
+
61
+ #The authorization_url takes 1 of 3 arguments depending on how much access you want to grant yourself:
62
+ #(:read_only, :read_write or :full_control)
63
+
64
+ puts client.authorization_url(:full_control)
65
+
66
+ #This will output a really long URL, copy and paste this URL into a browser and you'll be prompted by Google
67
+ #to allow access to your google storage account.
68
+ #Accept this request and your browser will redirect to a "PAGE NOT FOUND" error most likely. This is fine.
69
+ #In your browsers URL now though, you should see something like this:
70
+
71
+ http://localhost:3000/example?code=4/oSdp5JUOiTVcq9p6SW6rjAfrdkuG.wngsnANBsI4RgrKXntQAax1m82kodAI
72
+
73
+ #This is an authentication token. Copy the token from this URL and issue one more command in IRB:
74
+
75
+ puts client.acquire_refresh_token('4/oSdp5JUOiTVcq9p6SW6rjAfrdkuG.wngsnANBsI4RgrKXntQAax1m82kodAI')
76
+
77
+ #Copy the output result from this command into the bottom of your google_storage.yml file
78
+
79
+ refresh_token: 1/Lyti64r-CmpYTpmXC6n4zKK84oh__6yArTPfgANTP9f
80
+
81
+ #You should now be setup and able to perform the commands in the 'Examples' section below.
82
+
83
+ </pre>
59
84
 
60
85
 
61
86
  h2. Setup your Google Project Client ID's
@@ -63,15 +88,16 @@ h2. Setup your Google Project Client ID's
63
88
  Visit "Google Storage":http://code.google.com/apis/storage/ and select activate Google Storage.
64
89
  If you haven't already got a project set up, it'll prompt you to create one.
65
90
 
66
- When you have access to your Google APIs Console, you need to enable Google Storage. When you select enable, you'll be shown terms and conditions
67
- and you'll then need to setup billing. They have full pricing details there for you to check out as well but I think it's pretty reasonable..
91
+ When you have access to your Google APIs Console, you need to enable Google Storage. When you select enable, you'll be shown terms
92
+ and conditions and you'll then need to setup billing. They have full pricing details there for you to check out as well but I think
93
+ it's pretty reasonable..
68
94
 
69
95
  Create a client ID for your project
70
96
  On the left menu select "API Access" and then "Create an OAuth 2.0 client ID"
71
97
  Enter your project's name and brand information.
72
98
 
73
- Select Application type = Web Application and enter your site's information. If you're using localhost and running
74
- locally make sure you include the port number you're using as well.
99
+ Select Application type = Web Application and enter your site's information. If you're using localhost and running locally make sure
100
+ you include the port number you're using as well.
75
101
 
76
102
 
77
103
  h2. Enter your Client ID details into your google_storage.yml
@@ -133,6 +159,34 @@ web_applications:
133
159
  Once you've acquired your refresh_token you can now make calls to the API.
134
160
 
135
161
 
162
+ h2. Response Object
163
+
164
+ A lot of the responses from GS on the backend are a little bit inconsistent, sometimes returning response codes, sometimes returning
165
+ heavily nested xml data and sometimes just returning information in the response header. I've tried to parse all responses that are
166
+ returned from GS into a fairly consistent type of response Hash object.
167
+ Usually this is in the form of something like this:
168
+
169
+ <pre>
170
+ #successful responses will always include a :success => true key/value pair
171
+
172
+ client.list_buckets
173
+ => {:success=>true,
174
+ :buckets=>[ {"Name"=>"bucket_1_example", "CreationDate"=>"2011-06-07T07:11:18.480Z"},
175
+ {"Name"=>"bucket_2_example", "CreationDate"=>"2011-05-31T10:58:08.097Z"},
176
+ {"Name"=>"bucket_3_example", "CreationDate"=>"2011-06-06T22:47:10.728Z"}],
177
+ :raw=>{ THIS :raw FIELD WILL RETURN A HASH OF THE UNPARSED RESPONSE IN CASE YOU NEED IT }
178
+ }
179
+
180
+ #Unsuccessful responses will return an "Error" Hash
181
+
182
+ client.get_bucket("bucket_4_example")
183
+ => {"Error"=>{
184
+ "Code"=>"NoSuchBucket",
185
+ "Message"=>"The specified bucket does not exist."
186
+ }}
187
+ </pre>
188
+
189
+
136
190
  h2. Examples
137
191
 
138
192
  h3. Configuration
@@ -143,7 +197,7 @@ h3. Configuration
143
197
  <pre>client = GoogleStorage::Client.new</pre>
144
198
 
145
199
  Otherwise you can pass in the path to the google_storage.yml
146
- <pre>client = GoogleStorage::Client.new(:config_yml => 'C:/github/highvoltage/config/google_storage.yml')
200
+ <pre>client = GoogleStorage::Client.new(:config_yml => 'C:/rails_app/config/google_storage.yml')
147
201
  </pre>
148
202
 
149
203
  h3. Service Requests
@@ -173,15 +227,15 @@ h3. Object Requests
173
227
 
174
228
  GET Object
175
229
  <pre>client.get_object('bucket_name', 'filename.jpg')
176
- client.get_object('bucket_name', 'filename.jpg', :write_to_file => 'c:/temp/new_file_name.jpg')</pre>
230
+ client.get_object('bucket_name', 'filename.jpg', :write_to_file => 'c:/example/new_file_name.jpg')</pre>
177
231
 
178
232
  POST Object
179
233
  <pre>Sorry, not including a 'post' object method as it still requires use of the old legacy access,
180
234
  Please use the 'put' object method below instead to upload files to a bucket.</pre>
181
235
 
182
236
  PUT Object
183
- <pre>client.put_object('bucket_name', 'filename.jpg', :data => File.read('c:/temp/file.jpg'), :x_goog_acl => 'public-read')
184
- client.upload_object('bucket_name', 'filename.jpg', :path_to_file => 'c:/temp/file.jpg')</pre>
237
+ <pre>client.put_object('bucket_name', 'filename.jpg', :data => File.read('c:/example/file.jpg'), :x_goog_acl => 'public-read')
238
+ client.upload_object('bucket_name', 'filename.jpg', :path_to_file => 'c:/example/file.jpg')</pre>
185
239
 
186
240
  HEAD Object
187
241
  <pre>client.object_head('bucket_name', 'filename.jpg')</pre>
@@ -191,4 +245,38 @@ h3. Object Requests
191
245
 
192
246
 
193
247
 
248
+ h2. Contributions made by (and thanks to) the following people:
249
+
250
+ Brian Armstrong
251
+ Peter Graham
252
+ ilyakatz
253
+ karlentwistle
254
+
255
+
256
+ h2. License
257
+
258
+ MIT License
259
+
260
+ Copyright (C) 2011 by Lucas Hills
261
+
262
+ Permission is hereby granted, free of charge, to any person obtaining a copy
263
+ of this software and associated documentation files (the "Software"), to deal
264
+ in the Software without restriction, including without limitation the rights
265
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
266
+ copies of the Software, and to permit persons to whom the Software is
267
+ furnished to do so, subject to the following conditions:
268
+
269
+ The above copyright notice and this permission notice shall be included in
270
+ all copies or substantial portions of the Software.
271
+
272
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
273
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
274
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
275
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
276
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
277
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
278
+ THE SOFTWARE.
279
+
280
+
281
+
194
282
 
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ##
4
+ # Title: google_storage
5
+ # Contact: https://github.com/2potatocakes/google_storage
6
+ ##
7
+
8
+ require 'fileutils'
9
+
10
+ ##
11
+ # The following script will generate a google_storage.yml template file in the directory
12
+ # where the script is executed from
13
+ #
14
+ # Usage: deploy_gs_yml
15
+ #
16
+ ##
17
+
18
+ class GSYml
19
+
20
+ def self.deploy
21
+ gs_yml = File.expand_path(File.join(Dir.pwd, "google_storage.yml"))
22
+ if File.exists?(gs_yml)
23
+ puts "google_storage.yml already exists in this directory"
24
+ else
25
+ FileUtils.cp File.expand_path("../lib/generators/templates/google_storage.yml", File.dirname(__FILE__)),
26
+ gs_yml
27
+
28
+ puts "Successfully generated: #{gs_yml}"
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ GSYml.deploy
@@ -12,7 +12,8 @@ Gem::Specification.new do |s|
12
12
  s.homepage = 'https://github.com/2potatocakes/google_storage'
13
13
  s.summary = 'Google Storage for Developers is a RESTful service for storing and accessing your data on Google\'s infrastructure'
14
14
  s.description = 'A Ruby client library for using the new Google Storage API v2 using OAuth2.0'
15
- s.files = `git ls-files`.split("\n")
15
+ s.files = %w(Rakefile README.textile google_storage.gemspec) + Dir.glob("{bin,lib}/**/*")
16
+ s.executables = %w(deploy_gs_yml)
16
17
  s.require_paths = ['lib']
17
18
 
18
19
  s.add_dependency('crack')
@@ -17,7 +17,7 @@ module GoogleStorage
17
17
  resp_obj = Crack::XML.parse(resp.body)
18
18
  if resp_obj["ListAllMyBucketsResult"]
19
19
  resp_obj[:success] = true
20
- resp_obj[:buckets] = resp_obj["ListAllMyBucketsResult"]["Buckets"]["Bucket"]
20
+ resp_obj[:buckets] = resp_obj["ListAllMyBucketsResult"]["Buckets"].nil? ? [] : resp_obj["ListAllMyBucketsResult"]["Buckets"]["Bucket"]
21
21
  resp_obj[:raw] = Crack::XML.parse(resp.body)
22
22
  resp_obj.each_key {|key| resp_obj.delete(key) unless key == :success || key == :buckets || key == :raw }
23
23
  end
@@ -100,6 +100,8 @@ Example: GoogleStorage::Client.new(:config_yml => 'path to your google storage y
100
100
  @debug = options[:debug]
101
101
  @timeout = options[:timeout]
102
102
  @host = options[:host] ? options[:host] : 'commondatastorage.googleapis.com'
103
+
104
+ @access_token = self.refresh_access_token(@refresh_token)["access_token"]
103
105
  end
104
106
 
105
107
 
@@ -160,5 +162,4 @@ Example: GoogleStorage::Client.new(:config_yml => 'path to your google storage y
160
162
  end
161
163
 
162
164
  end
163
- end
164
-
165
+ end
@@ -22,7 +22,7 @@ module GoogleStorage
22
22
  headers["Content-Length"] = (options[:data] ? options[:data].size : 0).to_s
23
23
  headers["x-goog-api-version"] = @api_version
24
24
  headers["x-goog-project-id"] = @project_id if options[:send_goog_project_id]
25
- headers["Authorization"] = 'OAuth ' + self.refresh_access_token(@refresh_token)["access_token"]
25
+ headers["Authorization"] = 'Bearer ' + @access_token
26
26
  param_string = params.empty? ? '' : '?' + params_to_data_string(params)
27
27
  headers["Range"] = options[:range] if options[:range]
28
28
  headers["If-Match"] = options[:filename] if options[:filename]
@@ -31,8 +31,16 @@ module GoogleStorage
31
31
  headers["If-Unmodified-Since"]= options[:if_modified_since] if options[:if_modified_since]
32
32
  headers["Content-MD5"] = options[:md5] if options[:md5]
33
33
  headers["x-goog-acl"] = options[:x_goog_acl] if options[:x_goog_acl]
34
+ headers["Transfer-Encoding"] = options[:transfer_encoding] if options[:transfer_encoding]
34
35
 
35
- _http_request(host, path, method, headers, param_string, options[:data])
36
+ request = _http_request(host, path, method, headers, param_string, options[:data])
37
+ if request.class == Net::HTTPUnauthorized
38
+ warn "Token expired, will attempt to get a new one" if @debug
39
+ @access_token = self.refresh_access_token(@refresh_token)["access_token"]
40
+ headers["Authorization"] = 'Bearer ' + @access_token
41
+ request = _http_request(host, path, method, headers, param_string, options[:data])
42
+ end
43
+ request
36
44
  end
37
45
 
38
46
  private
@@ -81,4 +89,4 @@ module GoogleStorage
81
89
  "#{esc_params.join('&')}"
82
90
  end
83
91
  end
84
- end
92
+ end
@@ -11,8 +11,17 @@ module GoogleStorage
11
11
  'https://www.googleapis.com/auth/devstorage.full_control'
12
12
  else
13
13
  'https://www.google.com/m8/feeds/'
14
- end
15
- "https://accounts.google.com/o/oauth2/auth?client_id=#{@client_id}&redirect_uri=#{@redirect_uri}&scope=#{scope_url}&response_type=code"
14
+ end
15
+
16
+ auth_url = "https://accounts.google.com/o/oauth2/auth?"
17
+ auth_url += "client_id=#{@client_id}&"
18
+ auth_url += "redirect_uri=#{@redirect_uri}&"
19
+ auth_url += "scope=#{scope_url}&"
20
+ auth_url += "response_type=code&"
21
+ auth_url += "access_type=offline&"
22
+ auth_url += "approval_prompt=force"
23
+
24
+ return auth_url
16
25
  end
17
26
 
18
27
  def acquire_refresh_token(token, options={})
@@ -1,3 +1,3 @@
1
1
  module GoogleStorage
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,92 +1,92 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: google_storage
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.2
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Lucas Hills
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2011-07-29 00:00:00.000000000Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2012-10-01 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: crack
16
- requirement: &10174068 !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
17
24
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
22
32
  type: :runtime
23
- prerelease: false
24
- version_requirements: *10174068
33
+ version_requirements: *id001
25
34
  description: A Ruby client library for using the new Google Storage API v2 using OAuth2.0
26
- email:
35
+ email:
27
36
  - lucas@lucashills.com
28
- executables: []
37
+ executables:
38
+ - deploy_gs_yml
29
39
  extensions: []
30
- extra_rdoc_files:
31
- - README.textile
32
- files:
33
- - .gitignore
34
- - .yardopts
35
- - Gemfile
40
+
41
+ extra_rdoc_files:
36
42
  - README.textile
43
+ files:
37
44
  - Rakefile
38
- - doc/GoogleStorage.html
39
- - doc/GoogleStorage/Client.html
40
- - doc/GoogleStorage/InstallGenerator.html
41
- - doc/_index.html
42
- - doc/class_list.html
43
- - doc/css/common.css
44
- - doc/css/full_list.css
45
- - doc/css/style.css
46
- - doc/file.README.html
47
- - doc/file_list.html
48
- - doc/frames.html
49
- - doc/index.html
50
- - doc/js/app.js
51
- - doc/js/full_list.js
52
- - doc/js/jquery.js
53
- - doc/method_list.html
54
- - doc/top-level-namespace.html
55
- - examples/examples.rb
45
+ - README.textile
56
46
  - google_storage.gemspec
47
+ - bin/deploy_gs_yml
57
48
  - lib/generators/google_storage/install/install_generator.rb
58
49
  - lib/generators/templates/google_storage.rake
59
50
  - lib/generators/templates/google_storage.yml
60
- - lib/google_storage.rb
61
51
  - lib/google_storage/bucket.rb
62
52
  - lib/google_storage/client.rb
63
53
  - lib/google_storage/object.rb
64
54
  - lib/google_storage/request.rb
65
55
  - lib/google_storage/token.rb
66
56
  - lib/google_storage/version.rb
57
+ - lib/google_storage.rb
67
58
  homepage: https://github.com/2potatocakes/google_storage
68
59
  licenses: []
60
+
69
61
  post_install_message:
70
62
  rdoc_options: []
71
- require_paths:
63
+
64
+ require_paths:
72
65
  - lib
73
- required_ruby_version: !ruby/object:Gem::Requirement
66
+ required_ruby_version: !ruby/object:Gem::Requirement
74
67
  none: false
75
- requirements:
76
- - - ! '>='
77
- - !ruby/object:Gem::Version
78
- version: '0'
79
- required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
76
  none: false
81
- requirements:
82
- - - ! '>='
83
- - !ruby/object:Gem::Version
84
- version: '0'
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ hash: 3
81
+ segments:
82
+ - 0
83
+ version: "0"
85
84
  requirements: []
85
+
86
86
  rubyforge_project:
87
- rubygems_version: 1.8.5
87
+ rubygems_version: 1.8.15
88
88
  signing_key:
89
89
  specification_version: 3
90
- summary: Google Storage for Developers is a RESTful service for storing and accessing
91
- your data on Google's infrastructure
90
+ summary: Google Storage for Developers is a RESTful service for storing and accessing your data on Google's infrastructure
92
91
  test_files: []
92
+