cure-google-api-client 0.8.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +178 -0
  3. data/Gemfile +9 -0
  4. data/LICENSE +202 -0
  5. data/README.md +218 -0
  6. data/Rakefile +41 -0
  7. data/google-api-client.gemspec +43 -0
  8. data/lib/cacerts.pem +2183 -0
  9. data/lib/compat/multi_json.rb +19 -0
  10. data/lib/google/api_client.rb +750 -0
  11. data/lib/google/api_client/auth/compute_service_account.rb +28 -0
  12. data/lib/google/api_client/auth/file_storage.rb +59 -0
  13. data/lib/google/api_client/auth/installed_app.rb +126 -0
  14. data/lib/google/api_client/auth/jwt_asserter.rb +126 -0
  15. data/lib/google/api_client/auth/key_utils.rb +93 -0
  16. data/lib/google/api_client/auth/pkcs12.rb +41 -0
  17. data/lib/google/api_client/auth/storage.rb +102 -0
  18. data/lib/google/api_client/auth/storages/file_store.rb +58 -0
  19. data/lib/google/api_client/auth/storages/redis_store.rb +54 -0
  20. data/lib/google/api_client/batch.rb +326 -0
  21. data/lib/google/api_client/charset.rb +33 -0
  22. data/lib/google/api_client/client_secrets.rb +179 -0
  23. data/lib/google/api_client/discovery.rb +19 -0
  24. data/lib/google/api_client/discovery/api.rb +310 -0
  25. data/lib/google/api_client/discovery/media.rb +77 -0
  26. data/lib/google/api_client/discovery/method.rb +363 -0
  27. data/lib/google/api_client/discovery/resource.rb +156 -0
  28. data/lib/google/api_client/discovery/schema.rb +117 -0
  29. data/lib/google/api_client/environment.rb +42 -0
  30. data/lib/google/api_client/errors.rb +65 -0
  31. data/lib/google/api_client/gzip.rb +28 -0
  32. data/lib/google/api_client/logging.rb +32 -0
  33. data/lib/google/api_client/media.rb +259 -0
  34. data/lib/google/api_client/railtie.rb +18 -0
  35. data/lib/google/api_client/reference.rb +27 -0
  36. data/lib/google/api_client/request.rb +350 -0
  37. data/lib/google/api_client/result.rb +255 -0
  38. data/lib/google/api_client/service.rb +233 -0
  39. data/lib/google/api_client/service/batch.rb +110 -0
  40. data/lib/google/api_client/service/request.rb +144 -0
  41. data/lib/google/api_client/service/resource.rb +40 -0
  42. data/lib/google/api_client/service/result.rb +162 -0
  43. data/lib/google/api_client/service/simple_file_store.rb +151 -0
  44. data/lib/google/api_client/service/stub_generator.rb +61 -0
  45. data/lib/google/api_client/service_account.rb +21 -0
  46. data/lib/google/api_client/version.rb +26 -0
  47. data/spec/google/api_client/auth/storage_spec.rb +122 -0
  48. data/spec/google/api_client/auth/storages/file_store_spec.rb +40 -0
  49. data/spec/google/api_client/auth/storages/redis_store_spec.rb +70 -0
  50. data/spec/google/api_client/batch_spec.rb +248 -0
  51. data/spec/google/api_client/client_secrets_spec.rb +53 -0
  52. data/spec/google/api_client/discovery_spec.rb +708 -0
  53. data/spec/google/api_client/gzip_spec.rb +98 -0
  54. data/spec/google/api_client/media_spec.rb +178 -0
  55. data/spec/google/api_client/request_spec.rb +29 -0
  56. data/spec/google/api_client/result_spec.rb +207 -0
  57. data/spec/google/api_client/service_account_spec.rb +169 -0
  58. data/spec/google/api_client/service_spec.rb +618 -0
  59. data/spec/google/api_client/simple_file_store_spec.rb +133 -0
  60. data/spec/google/api_client_spec.rb +352 -0
  61. data/spec/spec_helper.rb +66 -0
  62. metadata +339 -0
@@ -0,0 +1,117 @@
1
+ # Copyright 2010 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ require 'time'
17
+ require 'multi_json'
18
+ require 'compat/multi_json'
19
+ require 'base64'
20
+ require 'autoparse'
21
+ require 'addressable/uri'
22
+ require 'addressable/template'
23
+
24
+ require 'active_support/inflector'
25
+ require 'google/api_client/errors'
26
+
27
+
28
+ module Google
29
+ class APIClient
30
+ ##
31
+ # @api private
32
+ module Schema
33
+ def self.parse(api, schema_data)
34
+ # This method is super-long, but hard to break up due to the
35
+ # unavoidable dependence on closures and execution context.
36
+ schema_name = schema_data['id']
37
+
38
+ # Due to an oversight, schema IDs may not be URI references.
39
+ # TODO(bobaman): Remove this code once this has been resolved.
40
+ schema_uri = (
41
+ api.document_base +
42
+ (schema_name[0..0] != '#' ? '#' + schema_name : schema_name)
43
+ )
44
+
45
+ # Due to an oversight, schema IDs may not be URI references.
46
+ # TODO(bobaman): Remove this whole lambda once this has been resolved.
47
+ reformat_references = lambda do |data|
48
+ # This code is not particularly efficient due to recursive traversal
49
+ # and excess object creation, but this hopefully shouldn't be an
50
+ # issue since it should only be called only once per schema per
51
+ # process.
52
+ if data.kind_of?(Hash) &&
53
+ data['$ref'] && !data['$ref'].kind_of?(Hash)
54
+ if data['$ref'].respond_to?(:to_str)
55
+ reference = data['$ref'].to_str
56
+ else
57
+ raise TypeError, "Expected String, got #{data['$ref'].class}"
58
+ end
59
+ reference = '#' + reference if reference[0..0] != '#'
60
+ data.merge({
61
+ '$ref' => reference
62
+ })
63
+ elsif data.kind_of?(Hash)
64
+ data.inject({}) do |accu, (key, value)|
65
+ if value.kind_of?(Hash)
66
+ accu[key] = reformat_references.call(value)
67
+ else
68
+ accu[key] = value
69
+ end
70
+ accu
71
+ end
72
+ else
73
+ data
74
+ end
75
+ end
76
+ schema_data = reformat_references.call(schema_data)
77
+
78
+ if schema_name
79
+ api_name_string = ActiveSupport::Inflector.camelize(api.name)
80
+ api_version_string = ActiveSupport::Inflector.camelize(api.version).gsub('.', '_')
81
+ # This is for compatibility with Ruby 1.8.7.
82
+ # TODO(bobaman) Remove this when we eventually stop supporting 1.8.7.
83
+ args = []
84
+ args << false if Class.method(:const_defined?).arity != 1
85
+ if Google::APIClient::Schema.const_defined?(api_name_string, *args)
86
+ api_name = Google::APIClient::Schema.const_get(
87
+ api_name_string, *args
88
+ )
89
+ else
90
+ api_name = Google::APIClient::Schema.const_set(
91
+ api_name_string, Module.new
92
+ )
93
+ end
94
+ if api_name.const_defined?(api_version_string, *args)
95
+ api_version = api_name.const_get(api_version_string, *args)
96
+ else
97
+ api_version = api_name.const_set(api_version_string, Module.new)
98
+ end
99
+ if api_version.const_defined?(schema_name, *args)
100
+ schema_class = api_version.const_get(schema_name, *args)
101
+ end
102
+ end
103
+
104
+ # It's possible the schema has already been defined. If so, don't
105
+ # redefine it. This means that reloading a schema which has already
106
+ # been loaded into memory is not possible.
107
+ unless schema_class
108
+ schema_class = AutoParse.generate(schema_data, :uri => schema_uri)
109
+ if schema_name
110
+ api_version.const_set(schema_name, schema_class)
111
+ end
112
+ end
113
+ return schema_class
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,42 @@
1
+ # Copyright 2010 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ module Google
17
+ class APIClient
18
+ module ENV
19
+ OS_VERSION = begin
20
+ if RUBY_PLATFORM =~ /mswin|win32|mingw|bccwin|cygwin/
21
+ # TODO(bobaman)
22
+ # Confirm that all of these Windows environments actually have access
23
+ # to the `ver` command.
24
+ `ver`.sub(/\s*\[Version\s*/, '/').sub(']', '').strip
25
+ elsif RUBY_PLATFORM =~ /darwin/i
26
+ "Mac OS X/#{`sw_vers -productVersion`}"
27
+ elsif RUBY_PLATFORM == 'java'
28
+ # Get the information from java system properties to avoid spawning a
29
+ # sub-process, which is not friendly in some contexts (web servers).
30
+ require 'java'
31
+ name = java.lang.System.getProperty('os.name')
32
+ version = java.lang.System.getProperty('os.version')
33
+ "#{name}/#{version}"
34
+ else
35
+ `uname -sr`.sub(' ', '/')
36
+ end
37
+ rescue Exception
38
+ RUBY_PLATFORM
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,65 @@
1
+ # Copyright 2010 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ module Google
17
+ class APIClient
18
+ ##
19
+ # An error which is raised when there is an unexpected response or other
20
+ # transport error that prevents an operation from succeeding.
21
+ class TransmissionError < StandardError
22
+ attr_reader :result
23
+ def initialize(message = nil, result = nil)
24
+ super(message)
25
+ @result = result
26
+ end
27
+ end
28
+
29
+ ##
30
+ # An exception that is raised if a redirect is required
31
+ #
32
+ class RedirectError < TransmissionError
33
+ end
34
+
35
+ ##
36
+ # An exception that is raised if a method is called with missing or
37
+ # invalid parameter values.
38
+ class ValidationError < StandardError
39
+ end
40
+
41
+ ##
42
+ # A 4xx class HTTP error occurred.
43
+ class ClientError < TransmissionError
44
+ end
45
+
46
+ ##
47
+ # A 401 HTTP error occurred.
48
+ class AuthorizationError < ClientError
49
+ end
50
+
51
+ ##
52
+ # A 5xx class HTTP error occurred.
53
+ class ServerError < TransmissionError
54
+ end
55
+
56
+ ##
57
+ # An exception that is raised if an ID token could not be validated.
58
+ class InvalidIDTokenError < StandardError
59
+ end
60
+
61
+ # Error class for problems in batch requests.
62
+ class BatchError < StandardError
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,28 @@
1
+ require 'faraday'
2
+ require 'zlib'
3
+
4
+ module Google
5
+ class APIClient
6
+ class Gzip < Faraday::Response::Middleware
7
+ include Google::APIClient::Logging
8
+
9
+ def on_complete(env)
10
+ encoding = env[:response_headers]['content-encoding'].to_s.downcase
11
+ case encoding
12
+ when 'gzip'
13
+ logger.debug { "Decompressing gzip encoded response (#{env[:body].length} bytes)" }
14
+ env[:body] = Zlib::GzipReader.new(StringIO.new(env[:body])).read
15
+ env[:response_headers].delete('content-encoding')
16
+ logger.debug { "Decompressed (#{env[:body].length} bytes)" }
17
+ when 'deflate'
18
+ logger.debug{ "Decompressing deflate encoded response (#{env[:body].length} bytes)" }
19
+ env[:body] = Zlib::Inflate.inflate(env[:body])
20
+ env[:response_headers].delete('content-encoding')
21
+ logger.debug { "Decompressed (#{env[:body].length} bytes)" }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ Faraday::Response.register_middleware :gzip => Google::APIClient::Gzip
@@ -0,0 +1,32 @@
1
+ require 'logger'
2
+
3
+ module Google
4
+ class APIClient
5
+
6
+ class << self
7
+ ##
8
+ # Logger for the API client
9
+ #
10
+ # @return [Logger] logger instance.
11
+ attr_accessor :logger
12
+ end
13
+
14
+ self.logger = Logger.new(STDOUT)
15
+ self.logger.level = Logger::WARN
16
+
17
+ ##
18
+ # Module to make accessing the logger simpler
19
+ module Logging
20
+ ##
21
+ # Logger for the API client
22
+ #
23
+ # @return [Logger] logger instance.
24
+ def logger
25
+ Google::APIClient.logger
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+
32
+ end
@@ -0,0 +1,259 @@
1
+ # Copyright 2010 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ require 'google/api_client/reference'
15
+
16
+ module Google
17
+ class APIClient
18
+ ##
19
+ # Uploadable media support. Holds an IO stream & content type.
20
+ #
21
+ # @see Faraday::UploadIO
22
+ # @example
23
+ # media = Google::APIClient::UploadIO.new('mymovie.m4v', 'video/mp4')
24
+ class UploadIO < Faraday::UploadIO
25
+
26
+ # @return [Fixnum] Size of chunks to upload. Default is nil, meaning upload the entire file in a single request
27
+ attr_accessor :chunk_size
28
+
29
+ ##
30
+ # Get the length of the stream
31
+ #
32
+ # @return [Fixnum]
33
+ # Length of stream, in bytes
34
+ def length
35
+ io.respond_to?(:length) ? io.length : File.size(local_path)
36
+ end
37
+ end
38
+
39
+ ##
40
+ # Wraps an input stream and limits data to a given range
41
+ #
42
+ # @example
43
+ # chunk = Google::APIClient::RangedIO.new(io, 0, 1000)
44
+ class RangedIO
45
+ ##
46
+ # Bind an input stream to a specific range.
47
+ #
48
+ # @param [IO] io
49
+ # Source input stream
50
+ # @param [Fixnum] offset
51
+ # Starting offset of the range
52
+ # @param [Fixnum] length
53
+ # Length of range
54
+ def initialize(io, offset, length)
55
+ @io = io
56
+ @offset = offset
57
+ @length = length
58
+ self.rewind
59
+ end
60
+
61
+ ##
62
+ # @see IO#read
63
+ def read(amount = nil, buf = nil)
64
+ buffer = buf || ''
65
+ if amount.nil?
66
+ size = @length - @pos
67
+ done = ''
68
+ elsif amount == 0
69
+ size = 0
70
+ done = ''
71
+ else
72
+ size = [@length - @pos, amount].min
73
+ done = nil
74
+ end
75
+
76
+ if size > 0
77
+ result = @io.read(size)
78
+ result.force_encoding("BINARY") if result.respond_to?(:force_encoding)
79
+ buffer << result if result
80
+ @pos = @pos + size
81
+ end
82
+
83
+ if buffer.length > 0
84
+ buffer
85
+ else
86
+ done
87
+ end
88
+ end
89
+
90
+ ##
91
+ # @see IO#rewind
92
+ def rewind
93
+ self.pos = 0
94
+ end
95
+
96
+ ##
97
+ # @see IO#pos
98
+ def pos
99
+ @pos
100
+ end
101
+
102
+ ##
103
+ # @see IO#pos=
104
+ def pos=(pos)
105
+ @pos = pos
106
+ @io.pos = @offset + pos
107
+ end
108
+ end
109
+
110
+ ##
111
+ # Resumable uploader.
112
+ #
113
+ class ResumableUpload < Request
114
+ # @return [Fixnum] Max bytes to send in a single request
115
+ attr_accessor :chunk_size
116
+
117
+ ##
118
+ # Creates a new uploader.
119
+ #
120
+ # @param [Hash] options
121
+ # Request options
122
+ def initialize(options={})
123
+ super options
124
+ self.uri = options[:uri]
125
+ self.http_method = :put
126
+ @offset = options[:offset] || 0
127
+ @complete = false
128
+ @expired = false
129
+ end
130
+
131
+ ##
132
+ # Sends all remaining chunks to the server
133
+ #
134
+ # @deprecated Pass the instance to {Google::APIClient#execute} instead
135
+ #
136
+ # @param [Google::APIClient] api_client
137
+ # API Client instance to use for sending
138
+ def send_all(api_client)
139
+ result = nil
140
+ until complete?
141
+ result = send_chunk(api_client)
142
+ break unless result.status == 308
143
+ end
144
+ return result
145
+ end
146
+
147
+
148
+ ##
149
+ # Sends the next chunk to the server
150
+ #
151
+ # @deprecated Pass the instance to {Google::APIClient#execute} instead
152
+ #
153
+ # @param [Google::APIClient] api_client
154
+ # API Client instance to use for sending
155
+ def send_chunk(api_client)
156
+ return api_client.execute(self)
157
+ end
158
+
159
+ ##
160
+ # Check if upload is complete
161
+ #
162
+ # @return [TrueClass, FalseClass]
163
+ # Whether or not the upload complete successfully
164
+ def complete?
165
+ return @complete
166
+ end
167
+
168
+ ##
169
+ # Check if the upload URL expired (upload not completed in alotted time.)
170
+ # Expired uploads must be restarted from the beginning
171
+ #
172
+ # @return [TrueClass, FalseClass]
173
+ # Whether or not the upload has expired and can not be resumed
174
+ def expired?
175
+ return @expired
176
+ end
177
+
178
+ ##
179
+ # Check if upload is resumable. That is, neither complete nor expired
180
+ #
181
+ # @return [TrueClass, FalseClass] True if upload can be resumed
182
+ def resumable?
183
+ return !(self.complete? or self.expired?)
184
+ end
185
+
186
+ ##
187
+ # Convert to an HTTP request. Returns components in order of method, URI,
188
+ # request headers, and body
189
+ #
190
+ # @api private
191
+ #
192
+ # @return [Array<(Symbol, Addressable::URI, Hash, [#read,#to_str])>]
193
+ def to_http_request
194
+ if @complete
195
+ raise Google::APIClient::ClientError, "Upload already complete"
196
+ elsif @offset.nil?
197
+ self.headers.update({
198
+ 'Content-Length' => "0",
199
+ 'Content-Range' => "bytes */#{media.length}" })
200
+ else
201
+ start_offset = @offset
202
+ remaining = self.media.length - start_offset
203
+ chunk_size = self.media.chunk_size || self.chunk_size || self.media.length
204
+ content_length = [remaining, chunk_size].min
205
+ chunk = RangedIO.new(self.media.io, start_offset, content_length)
206
+ end_offset = start_offset + content_length - 1
207
+ self.headers.update({
208
+ 'Content-Length' => "#{content_length}",
209
+ 'Content-Type' => self.media.content_type,
210
+ 'Content-Range' => "bytes #{start_offset}-#{end_offset}/#{media.length}" })
211
+ self.body = chunk
212
+ end
213
+ super
214
+ end
215
+
216
+ ##
217
+ # Check the result from the server, updating the offset and/or location
218
+ # if available.
219
+ #
220
+ # @api private
221
+ #
222
+ # @param [Faraday::Response] response
223
+ # HTTP response
224
+ #
225
+ # @return [Google::APIClient::Result]
226
+ # Processed API response
227
+ def process_http_response(response)
228
+ case response.status
229
+ when 200...299
230
+ @complete = true
231
+ when 308
232
+ range = response.headers['range']
233
+ if range
234
+ @offset = range.scan(/\d+/).collect{|x| Integer(x)}.last + 1
235
+ end
236
+ if response.headers['location']
237
+ self.uri = response.headers['location']
238
+ end
239
+ when 400...499
240
+ @expired = true
241
+ when 500...599
242
+ # Invalidate the offset to mark it needs to be queried on the
243
+ # next request
244
+ @offset = nil
245
+ end
246
+ return Google::APIClient::Result.new(self, response)
247
+ end
248
+
249
+ ##
250
+ # Hashified verison of the API request
251
+ #
252
+ # @return [Hash]
253
+ def to_hash
254
+ super.merge(:offset => @offset)
255
+ end
256
+
257
+ end
258
+ end
259
+ end