diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d11caf68bc..b1be0e451fc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -40,7 +40,7 @@
# 0.7.0
* Remove CLI
* Support for automatic retires & backoff. Off by default, enable by setting `retries` on `APIClient`
-* Experimental new interface (see `Google::APIClient::Service`)
+* Experimental new interface (see `Legacy::Google::APIClient::Service`)
* Fix warnings when using Faraday separately
* Support Google Compute Engine service accounts
* Enable gzip compression for responses
diff --git a/README.md b/README.md
index 510ae817e9b..9e4bf982826 100644
--- a/README.md
+++ b/README.md
@@ -32,12 +32,12 @@ $ gem install google-api-client
## Example Usage
```ruby
-require 'google/api_client'
-require 'google/api_client/client_secrets'
-require 'google/api_client/auth/installed_app'
+require 'legacy/google/api_client'
+require 'legacy/google/api_client/client_secrets'
+require 'legacy/google/api_client/auth/installed_app'
# Initialize the client.
-client = Google::APIClient.new(
+client = Legacy::Google::APIClient.new(
:application_name => 'Example Ruby application',
:application_version => '1.0.0'
)
@@ -48,11 +48,11 @@ client = Google::APIClient.new(
plus = client.discovered_api('plus')
# Load client secrets from your client_secrets.json.
-client_secrets = Google::APIClient::ClientSecrets.load
+client_secrets = Legacy::Google::APIClient::ClientSecrets.load
# Run installed application flow. Check the samples for a more
# complete example that saves the credentials between runs.
-flow = Google::APIClient::InstalledAppFlow.new(
+flow = Legacy::Google::APIClient::InstalledAppFlow.new(
:client_id => client_secrets.client_id,
:client_secret => client_secrets.client_secret,
:scope => ['https://www.googleapis.com/auth/plus.me']
@@ -118,7 +118,7 @@ client.execute(...)
This is simpler API to use than in previous versions, although that is still available:
```ruby
-key = Google::APIClient::KeyUtils.load_from_pkcs12('client.p12', 'notasecret')
+key = Legacy::Google::APIClient::KeyUtils.load_from_pkcs12('client.p12', 'notasecret')
client.authorization = Signet::OAuth2::Client.new(
:token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
:audience => 'https://accounts.google.com/o/oauth2/token',
@@ -143,16 +143,16 @@ The default value for retries is 0, but will be enabled by default in future rel
### Batching Requests
-Some Google APIs support batching requests into a single HTTP request. Use `Google::APIClient::BatchRequest`
+Some Google APIs support batching requests into a single HTTP request. Use `Legacy::Google::APIClient::BatchRequest`
to bundle multiple requests together.
Example:
```ruby
-client = Google::APIClient.new
+client = Legacy::Google::APIClient.new
urlshortener = client.discovered_api('urlshortener')
-batch = Google::APIClient::BatchRequest.new do |result|
+batch = Legacy::Google::APIClient::BatchRequest.new do |result|
puts result.data
end
@@ -173,13 +173,13 @@ end
### Media Upload
-For APIs that support file uploads, use `Google::APIClient::UploadIO` to load the stream. Both multipart and resumable
+For APIs that support file uploads, use `Legacy::Google::APIClient::UploadIO` to load the stream. Both multipart and resumable
uploads can be used. For example, to upload a file to Google Drive using multipart
```ruby
drive = client.discovered_api('drive', 'v2')
-media = Google::APIClient::UploadIO.new('mymovie.m4v', 'video/mp4')
+media = Legacy::Google::APIClient::UploadIO.new('mymovie.m4v', 'video/mp4')
metadata = {
'title' => 'My movie',
'description' => 'The best home movie ever made'
diff --git a/Rakefile b/Rakefile
index dca3b090389..d95046a57b9 100644
--- a/Rakefile
+++ b/Rakefile
@@ -11,7 +11,7 @@ require File.join(File.dirname(__FILE__), 'lib/google/api_client', 'version')
PKG_DISPLAY_NAME = 'Google API Client'
PKG_NAME = PKG_DISPLAY_NAME.downcase.gsub(/\s/, '-')
-PKG_VERSION = Google::APIClient::VERSION::STRING
+PKG_VERSION = Legacy::Google::APIClient::VERSION::STRING
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
PKG_HOMEPAGE = 'https://github.com/google/google-api-ruby-client'
diff --git a/google-api-client.gemspec b/google-api-client.gemspec
index e5e34980588..6b48a2b744d 100644
--- a/google-api-client.gemspec
+++ b/google-api-client.gemspec
@@ -1,9 +1,9 @@
# -*- encoding: utf-8 -*-
-require File.join(File.dirname(__FILE__), 'lib/google/api_client', 'version')
+require File.join(File.dirname(__FILE__), 'lib/legacy/google/api_client', 'version')
Gem::Specification.new do |s|
s.name = "google-api-client"
- s.version = Google::APIClient::VERSION::STRING
+ s.version = Legacy::Google::APIClient::VERSION::STRING
s.required_rubygems_version = ">= 1.3.5"
s.require_paths = ["lib"]
diff --git a/lib/google/api_client.rb b/lib/google/api_client.rb
deleted file mode 100644
index ef3c2b1d34c..00000000000
--- a/lib/google/api_client.rb
+++ /dev/null
@@ -1,750 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-require 'faraday'
-require 'multi_json'
-require 'compat/multi_json'
-require 'stringio'
-require 'retriable'
-
-require 'google/api_client/version'
-require 'google/api_client/logging'
-require 'google/api_client/errors'
-require 'google/api_client/environment'
-require 'google/api_client/discovery'
-require 'google/api_client/request'
-require 'google/api_client/reference'
-require 'google/api_client/result'
-require 'google/api_client/media'
-require 'google/api_client/service_account'
-require 'google/api_client/batch'
-require 'google/api_client/gzip'
-require 'google/api_client/charset'
-require 'google/api_client/client_secrets'
-require 'google/api_client/railtie' if defined?(Rails)
-
-module Google
-
- ##
- # This class manages APIs communication.
- class APIClient
- include Google::APIClient::Logging
-
- ##
- # Creates a new Google API client.
- #
- # @param [Hash] options The configuration parameters for the client.
- # @option options [Symbol, #generate_authenticated_request] :authorization
- # (:oauth_1)
- # The authorization mechanism used by the client. The following
- # mechanisms are supported out-of-the-box:
- #
- # :two_legged_oauth_1
- # :oauth_1
- # :oauth_2
- # :google_app_default
- #
- # @option options [Boolean] :auto_refresh_token (true)
- # The setting that controls whether or not the api client attempts to
- # refresh authorization when a 401 is hit in #execute. If the token does
- # not support it, this option is ignored.
- # @option options [String] :application_name
- # The name of the application using the client.
- # @option options [String | Array | nil] :scope
- # The scope(s) used when using google application default credentials
- # @option options [String] :application_version
- # The version number of the application using the client.
- # @option options [String] :user_agent
- # ("{app_name} google-api-ruby-client/{version} {os_name}/{os_version}")
- # The user agent used by the client. Most developers will want to
- # leave this value alone and use the `:application_name` option instead.
- # @option options [String] :host ("www.googleapis.com")
- # The API hostname used by the client. This rarely needs to be changed.
- # @option options [String] :port (443)
- # The port number used by the client. This rarely needs to be changed.
- # @option options [String] :discovery_path ("/discovery/v1")
- # The discovery base path. This rarely needs to be changed.
- # @option options [String] :ca_file
- # Optional set of root certificates to use when validating SSL connections.
- # By default, a bundled set of trusted roots will be used.
- # @options options[Hash] :force_encoding
- # Experimental option. True if response body should be force encoded into the charset
- # specified in the Content-Type header. Mostly intended for compressed content.
- # @options options[Hash] :faraday_options
- # Pass through of options to set on the Faraday connection
- def initialize(options={})
- logger.debug { "#{self.class} - Initializing client with options #{options}" }
-
- # Normalize key to String to allow indifferent access.
- options = options.inject({}) do |accu, (key, value)|
- accu[key.to_sym] = value
- accu
- end
- # Almost all API usage will have a host of 'www.googleapis.com'.
- self.host = options[:host] || 'www.googleapis.com'
- self.port = options[:port] || 443
- self.discovery_path = options[:discovery_path] || '/discovery/v1'
-
- # Most developers will want to leave this value alone and use the
- # application_name option.
- if options[:application_name]
- app_name = options[:application_name]
- app_version = options[:application_version]
- application_string = "#{app_name}/#{app_version || '0.0.0'}"
- else
- logger.warn { "#{self.class} - Please provide :application_name and :application_version when initializing the client" }
- end
-
- proxy = options[:proxy] || Object::ENV["http_proxy"]
-
- self.user_agent = options[:user_agent] || (
- "#{application_string} " +
- "google-api-ruby-client/#{Google::APIClient::VERSION::STRING} #{ENV::OS_VERSION} (gzip)"
- ).strip
- # The writer method understands a few Symbols and will generate useful
- # default authentication mechanisms.
- self.authorization =
- options.key?(:authorization) ? options[:authorization] : :oauth_2
- if !options['scope'].nil? and self.authorization.respond_to?(:scope=)
- self.authorization.scope = options['scope']
- end
- self.auto_refresh_token = options.fetch(:auto_refresh_token) { true }
- self.key = options[:key]
- self.user_ip = options[:user_ip]
- self.retries = options.fetch(:retries) { 0 }
- self.expired_auth_retry = options.fetch(:expired_auth_retry) { true }
- @discovery_uris = {}
- @discovery_documents = {}
- @discovered_apis = {}
- ca_file = options[:ca_file] || File.expand_path('../../cacerts.pem', __FILE__)
- self.connection = Faraday.new do |faraday|
- faraday.response :charset if options[:force_encoding]
- faraday.response :gzip
- faraday.options.params_encoder = Faraday::FlatParamsEncoder
- faraday.ssl.ca_file = ca_file
- faraday.ssl.verify = true
- faraday.proxy proxy
- faraday.adapter Faraday.default_adapter
- if options[:faraday_option].is_a?(Hash)
- options[:faraday_option].each_pair do |option, value|
- faraday.options.send("#{option}=", value)
- end
- end
- end
- return self
- end
-
- ##
- # Returns the authorization mechanism used by the client.
- #
- # @return [#generate_authenticated_request] The authorization mechanism.
- attr_reader :authorization
-
- ##
- # Sets the authorization mechanism used by the client.
- #
- # @param [#generate_authenticated_request] new_authorization
- # The new authorization mechanism.
- def authorization=(new_authorization)
- case new_authorization
- when :oauth_1, :oauth
- require 'signet/oauth_1/client'
- # NOTE: Do not rely on this default value, as it may change
- new_authorization = Signet::OAuth1::Client.new(
- :temporary_credential_uri =>
- 'https://www.google.com/accounts/OAuthGetRequestToken',
- :authorization_uri =>
- 'https://www.google.com/accounts/OAuthAuthorizeToken',
- :token_credential_uri =>
- 'https://www.google.com/accounts/OAuthGetAccessToken',
- :client_credential_key => 'anonymous',
- :client_credential_secret => 'anonymous'
- )
- when :two_legged_oauth_1, :two_legged_oauth
- require 'signet/oauth_1/client'
- # NOTE: Do not rely on this default value, as it may change
- new_authorization = Signet::OAuth1::Client.new(
- :client_credential_key => nil,
- :client_credential_secret => nil,
- :two_legged => true
- )
- when :google_app_default
- require 'googleauth'
- new_authorization = Google::Auth.get_application_default
-
- when :oauth_2
- require 'signet/oauth_2/client'
- # NOTE: Do not rely on this default value, as it may change
- new_authorization = Signet::OAuth2::Client.new(
- :authorization_uri =>
- 'https://accounts.google.com/o/oauth2/auth',
- :token_credential_uri =>
- 'https://accounts.google.com/o/oauth2/token'
- )
- when nil
- # No authorization mechanism
- else
- if !new_authorization.respond_to?(:generate_authenticated_request)
- raise TypeError,
- 'Expected authorization mechanism to respond to ' +
- '#generate_authenticated_request.'
- end
- end
- @authorization = new_authorization
- return @authorization
- end
-
- ##
- # Default Faraday/HTTP connection.
- #
- # @return [Faraday::Connection]
- attr_accessor :connection
-
- ##
- # The setting that controls whether or not the api client attempts to
- # refresh authorization when a 401 is hit in #execute.
- #
- # @return [Boolean]
- attr_accessor :auto_refresh_token
-
- ##
- # The application's API key issued by the API console.
- #
- # @return [String] The API key.
- attr_accessor :key
-
- ##
- # The IP address of the user this request is being performed on behalf of.
- #
- # @return [String] The user's IP address.
- attr_accessor :user_ip
-
- ##
- # The user agent used by the client.
- #
- # @return [String]
- # The user agent string used in the User-Agent header.
- attr_accessor :user_agent
-
- ##
- # The API hostname used by the client.
- #
- # @return [String]
- # The API hostname. Should almost always be 'www.googleapis.com'.
- attr_accessor :host
-
- ##
- # The port number used by the client.
- #
- # @return [String]
- # The port number. Should almost always be 443.
- attr_accessor :port
-
- ##
- # The base path used by the client for discovery.
- #
- # @return [String]
- # The base path. Should almost always be '/discovery/v1'.
- attr_accessor :discovery_path
-
- ##
- # Number of times to retry on recoverable errors
- #
- # @return [FixNum]
- # Number of retries
- attr_accessor :retries
-
- ##
- # Whether or not an expired auth token should be re-acquired
- # (and the operation retried) regardless of retries setting
- # @return [Boolean]
- # Auto retry on auth expiry
- attr_accessor :expired_auth_retry
-
- ##
- # Returns the URI for the directory document.
- #
- # @return [Addressable::URI] The URI of the directory document.
- def directory_uri
- return resolve_uri(self.discovery_path + '/apis')
- end
-
- ##
- # Manually registers a URI as a discovery document for a specific version
- # of an API.
- #
- # @param [String, Symbol] api The API name.
- # @param [String] version The desired version of the API.
- # @param [Addressable::URI] uri The URI of the discovery document.
- # @return [Google::APIClient::API] The service object.
- def register_discovery_uri(api, version, uri)
- api = api.to_s
- version = version || 'v1'
- @discovery_uris["#{api}:#{version}"] = uri
- discovered_api(api, version)
- end
-
- ##
- # Returns the URI for the discovery document.
- #
- # @param [String, Symbol] api The API name.
- # @param [String] version The desired version of the API.
- # @return [Addressable::URI] The URI of the discovery document.
- def discovery_uri(api, version=nil)
- api = api.to_s
- version = version || 'v1'
- return @discovery_uris["#{api}:#{version}"] ||= (
- resolve_uri(
- self.discovery_path + '/apis/{api}/{version}/rest',
- 'api' => api,
- 'version' => version
- )
- )
- end
-
- ##
- # Manually registers a pre-loaded discovery document for a specific version
- # of an API.
- #
- # @param [String, Symbol] api The API name.
- # @param [String] version The desired version of the API.
- # @param [String, StringIO] discovery_document
- # The contents of the discovery document.
- # @return [Google::APIClient::API] The service object.
- def register_discovery_document(api, version, discovery_document)
- api = api.to_s
- version = version || 'v1'
- if discovery_document.kind_of?(StringIO)
- discovery_document.rewind
- discovery_document = discovery_document.string
- elsif discovery_document.respond_to?(:to_str)
- discovery_document = discovery_document.to_str
- else
- raise TypeError,
- "Expected String or StringIO, got #{discovery_document.class}."
- end
- @discovery_documents["#{api}:#{version}"] =
- MultiJson.load(discovery_document)
- discovered_api(api, version)
- end
-
- ##
- # Returns the parsed directory document.
- #
- # @return [Hash] The parsed JSON from the directory document.
- def directory_document
- return @directory_document ||= (begin
- response = self.execute!(
- :http_method => :get,
- :uri => self.directory_uri,
- :authenticated => false
- )
- response.data
- end)
- end
-
- ##
- # Returns the parsed discovery document.
- #
- # @param [String, Symbol] api The API name.
- # @param [String] version The desired version of the API.
- # @return [Hash] The parsed JSON from the discovery document.
- def discovery_document(api, version=nil)
- api = api.to_s
- version = version || 'v1'
- return @discovery_documents["#{api}:#{version}"] ||= (begin
- response = self.execute!(
- :http_method => :get,
- :uri => self.discovery_uri(api, version),
- :authenticated => false
- )
- response.data
- end)
- end
-
- ##
- # Returns all APIs published in the directory document.
- #
- # @return [Array] The list of available APIs.
- def discovered_apis
- @directory_apis ||= (begin
- document_base = self.directory_uri
- if self.directory_document && self.directory_document['items']
- self.directory_document['items'].map do |discovery_document|
- Google::APIClient::API.new(
- document_base,
- discovery_document
- )
- end
- else
- []
- end
- end)
- end
-
- ##
- # Returns the service object for a given service name and service version.
- #
- # @param [String, Symbol] api The API name.
- # @param [String] version The desired version of the API.
- #
- # @return [Google::APIClient::API] The service object.
- def discovered_api(api, version=nil)
- if !api.kind_of?(String) && !api.kind_of?(Symbol)
- raise TypeError,
- "Expected String or Symbol, got #{api.class}."
- end
- api = api.to_s
- version = version || 'v1'
- return @discovered_apis["#{api}:#{version}"] ||= begin
- document_base = self.discovery_uri(api, version)
- discovery_document = self.discovery_document(api, version)
- if document_base && discovery_document
- Google::APIClient::API.new(
- document_base,
- discovery_document
- )
- else
- nil
- end
- end
- end
-
- ##
- # Returns the method object for a given RPC name and service version.
- #
- # @param [String, Symbol] rpc_name The RPC name of the desired method.
- # @param [String, Symbol] api The API the method is within.
- # @param [String] version The desired version of the API.
- #
- # @return [Google::APIClient::Method] The method object.
- def discovered_method(rpc_name, api, version=nil)
- if !rpc_name.kind_of?(String) && !rpc_name.kind_of?(Symbol)
- raise TypeError,
- "Expected String or Symbol, got #{rpc_name.class}."
- end
- rpc_name = rpc_name.to_s
- api = api.to_s
- version = version || 'v1'
- service = self.discovered_api(api, version)
- if service.to_h[rpc_name]
- return service.to_h[rpc_name]
- else
- return nil
- end
- end
-
- ##
- # Returns the service object with the highest version number.
- #
- # @note Warning: This method should be used with great care.
- # As APIs are updated, minor differences between versions may cause
- # incompatibilities. Requesting a specific version will avoid this issue.
- #
- # @param [String, Symbol] api The name of the service.
- #
- # @return [Google::APIClient::API] The service object.
- def preferred_version(api)
- if !api.kind_of?(String) && !api.kind_of?(Symbol)
- raise TypeError,
- "Expected String or Symbol, got #{api.class}."
- end
- api = api.to_s
- return self.discovered_apis.detect do |a|
- a.name == api && a.preferred == true
- end
- end
-
- ##
- # Verifies an ID token against a server certificate. Used to ensure that
- # an ID token supplied by an untrusted client-side mechanism is valid.
- # Raises an error if the token is invalid or missing.
- #
- # @deprecated Use the google-id-token gem for verifying JWTs
- def verify_id_token!
- require 'jwt'
- require 'openssl'
- @certificates ||= {}
- if !self.authorization.respond_to?(:id_token)
- raise ArgumentError, (
- "Current authorization mechanism does not support ID tokens: " +
- "#{self.authorization.class.to_s}"
- )
- elsif !self.authorization.id_token
- raise ArgumentError, (
- "Could not verify ID token, ID token missing. " +
- "Scopes were: #{self.authorization.scope.inspect}"
- )
- else
- check_cached_certs = lambda do
- valid = false
- for _key, cert in @certificates
- begin
- self.authorization.decoded_id_token(cert.public_key)
- valid = true
- rescue JWT::DecodeError, Signet::UnsafeOperationError
- # Expected exception. Ignore, ID token has not been validated.
- end
- end
- valid
- end
- if check_cached_certs.call()
- return true
- end
- response = self.execute!(
- :http_method => :get,
- :uri => 'https://www.googleapis.com/oauth2/v1/certs',
- :authenticated => false
- )
- @certificates.merge!(
- Hash[MultiJson.load(response.body).map do |key, cert|
- [key, OpenSSL::X509::Certificate.new(cert)]
- end]
- )
- if check_cached_certs.call()
- return true
- else
- raise InvalidIDTokenError,
- "Could not verify ID token against any available certificate."
- end
- end
- return nil
- end
-
- ##
- # Generates a request.
- #
- # @option options [Google::APIClient::Method] :api_method
- # The method object or the RPC name of the method being executed.
- # @option options [Hash, Array] :parameters
- # The parameters to send to the method.
- # @option options [Hash, Array] :headers The HTTP headers for the request.
- # @option options [String] :body The body of the request.
- # @option options [String] :version ("v1")
- # The service version. Only used if `api_method` is a `String`.
- # @option options [#generate_authenticated_request] :authorization
- # The authorization mechanism for the response. Used only if
- # `:authenticated` is `true`.
- # @option options [TrueClass, FalseClass] :authenticated (true)
- # `true` if the request must be signed or somehow
- # authenticated, `false` otherwise.
- #
- # @return [Google::APIClient::Reference] The generated request.
- #
- # @example
- # request = client.generate_request(
- # :api_method => 'plus.activities.list',
- # :parameters =>
- # {'collection' => 'public', 'userId' => 'me'}
- # )
- def generate_request(options={})
- options = {
- :api_client => self
- }.merge(options)
- return Google::APIClient::Request.new(options)
- end
-
- ##
- # Executes a request, wrapping it in a Result object.
- #
- # @param [Google::APIClient::Request, Hash, Array] params
- # Either a Google::APIClient::Request, a Hash, or an Array.
- #
- # If a Google::APIClient::Request, no other parameters are expected.
- #
- # If a Hash, the below parameters are handled. If an Array, the
- # parameters are assumed to be in the below order:
- #
- # - (Google::APIClient::Method) api_method:
- # The method object or the RPC name of the method being executed.
- # - (Hash, Array) parameters:
- # The parameters to send to the method.
- # - (String) body: The body of the request.
- # - (Hash, Array) headers: The HTTP headers for the request.
- # - (Hash) options: A set of options for the request, of which:
- # - (#generate_authenticated_request) :authorization (default: true) -
- # The authorization mechanism for the response. Used only if
- # `:authenticated` is `true`.
- # - (TrueClass, FalseClass) :authenticated (default: true) -
- # `true` if the request must be signed or somehow
- # authenticated, `false` otherwise.
- # - (TrueClass, FalseClass) :gzip (default: true) -
- # `true` if gzip enabled, `false` otherwise.
- # - (FixNum) :retries -
- # # of times to retry on recoverable errors
- #
- # @return [Google::APIClient::Result] The result from the API, nil if batch.
- #
- # @example
- # result = client.execute(batch_request)
- #
- # @example
- # plus = client.discovered_api('plus')
- # result = client.execute(
- # :api_method => plus.activities.list,
- # :parameters => {'collection' => 'public', 'userId' => 'me'}
- # )
- #
- # @see Google::APIClient#generate_request
- def execute!(*params)
- if params.first.kind_of?(Google::APIClient::Request)
- request = params.shift
- options = params.shift || {}
- else
- # This block of code allows us to accept multiple parameter passing
- # styles, and maintaining some backwards compatibility.
- #
- # Note: I'm extremely tempted to deprecate this style of execute call.
- if params.last.respond_to?(:to_hash) && params.size == 1
- options = params.pop
- else
- options = {}
- end
-
- options[:api_method] = params.shift if params.size > 0
- options[:parameters] = params.shift if params.size > 0
- options[:body] = params.shift if params.size > 0
- options[:headers] = params.shift if params.size > 0
- options.update(params.shift) if params.size > 0
- request = self.generate_request(options)
- end
-
- request.headers['User-Agent'] ||= '' + self.user_agent unless self.user_agent.nil?
- request.headers['Accept-Encoding'] ||= 'gzip' unless options[:gzip] == false
- request.headers['Content-Type'] ||= ''
- request.parameters['key'] ||= self.key unless self.key.nil?
- request.parameters['userIp'] ||= self.user_ip unless self.user_ip.nil?
-
- connection = options[:connection] || self.connection
- request.authorization = options[:authorization] || self.authorization unless options[:authenticated] == false
-
- tries = 1 + (options[:retries] || self.retries)
- attempt = 0
-
- Retriable.retriable :tries => tries,
- :on => [TransmissionError],
- :on_retry => client_error_handler,
- :interval => lambda {|attempts| (2 ** attempts) + rand} do
- attempt += 1
-
- # This 2nd level retriable only catches auth errors, and supports 1 retry, which allows
- # auth to be re-attempted without having to retry all sorts of other failures like
- # NotFound, etc
- Retriable.retriable :tries => ((expired_auth_retry || tries > 1) && attempt == 1) ? 2 : 1,
- :on => [AuthorizationError],
- :on_retry => authorization_error_handler(request.authorization) do
- result = request.send(connection, true)
-
- case result.status
- when 200...300
- result
- when 301, 302, 303, 307
- request = generate_request(request.to_hash.merge({
- :uri => result.headers['location'],
- :api_method => nil
- }))
- raise RedirectError.new(result.headers['location'], result)
- when 401
- raise AuthorizationError.new(result.error_message || 'Invalid/Expired Authentication', result)
- when 400, 402...500
- raise ClientError.new(result.error_message || "A client error has occurred", result)
- when 500...600
- raise ServerError.new(result.error_message || "A server error has occurred", result)
- else
- raise TransmissionError.new(result.error_message || "A transmission error has occurred", result)
- end
- end
- end
- end
-
- ##
- # Same as Google::APIClient#execute!, but does not raise an exception for
- # normal API errros.
- #
- # @see Google::APIClient#execute
- def execute(*params)
- begin
- return self.execute!(*params)
- rescue TransmissionError => e
- return e.result
- end
- end
-
- protected
-
- ##
- # Resolves a URI template against the client's configured base.
- #
- # @api private
- # @param [String, Addressable::URI, Addressable::Template] template
- # The template to resolve.
- # @param [Hash] mapping The mapping that corresponds to the template.
- # @return [Addressable::URI] The expanded URI.
- def resolve_uri(template, mapping={})
- @base_uri ||= Addressable::URI.new(
- :scheme => 'https',
- :host => self.host,
- :port => self.port
- ).normalize
- template = if template.kind_of?(Addressable::Template)
- template.pattern
- elsif template.respond_to?(:to_str)
- template.to_str
- else
- raise TypeError,
- "Expected String, Addressable::URI, or Addressable::Template, " +
- "got #{template.class}."
- end
- return Addressable::Template.new(@base_uri + template).expand(mapping)
- end
-
-
- ##
- # Returns on proc for special processing of retries for authorization errors
- # Only 401s should be retried and only if the credentials are refreshable
- #
- # @param [#fetch_access_token!] authorization
- # OAuth 2 credentials
- # @return [Proc]
- def authorization_error_handler(authorization)
- can_refresh = authorization.respond_to?(:refresh_token) && auto_refresh_token
- Proc.new do |exception, tries|
- next unless exception.kind_of?(AuthorizationError)
- if can_refresh
- begin
- logger.debug("Attempting refresh of access token & retry of request")
- authorization.fetch_access_token!
- next
- rescue Signet::AuthorizationError
- end
- end
- raise exception
- end
- end
-
- ##
- # Returns on proc for special processing of retries as not all client errors
- # are recoverable. Only 401s should be retried (via authorization_error_handler)
- #
- # @return [Proc]
- def client_error_handler
- Proc.new do |exception, tries|
- raise exception if exception.kind_of?(ClientError)
- end
- end
-
- end
-
-end
diff --git a/lib/google/api_client/auth/file_storage.rb b/lib/google/api_client/auth/file_storage.rb
deleted file mode 100644
index b3d01716600..00000000000
--- a/lib/google/api_client/auth/file_storage.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright 2013 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'signet/oauth_2/client'
-require_relative 'storage'
-require_relative 'storages/file_store'
-
-module Google
- class APIClient
-
- ##
- # Represents cached OAuth 2 tokens stored on local disk in a
- # JSON serialized file. Meant to resemble the serialized format
- # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
- #
- # @deprecated
- # Use {Google::APIClient::Storage} and {Google::APIClient::FileStore} instead
- #
- class FileStorage
-
- attr_accessor :storage
-
- def initialize(path)
- store = Google::APIClient::FileStore.new(path)
- @storage = Google::APIClient::Storage.new(store)
- @storage.authorize
- end
-
- def load_credentials
- storage.authorize
- end
-
- def authorization
- storage.authorization
- end
-
- ##
- # Write the credentials to the specified file.
- #
- # @param [Signet::OAuth2::Client] authorization
- # Optional authorization instance. If not provided, the authorization
- # already associated with this instance will be written.
- def write_credentials(auth=nil)
- storage.write_credentials(auth)
- end
- end
- end
-end
diff --git a/lib/google/api_client/auth/installed_app.rb b/lib/google/api_client/auth/installed_app.rb
deleted file mode 100644
index bdbb655d530..00000000000
--- a/lib/google/api_client/auth/installed_app.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'webrick'
-require 'launchy'
-
-module Google
- class APIClient
-
- # Small helper for the sample apps for performing OAuth 2.0 flows from the command
- # line or in any other installed app environment.
- #
- # @example
- #
- # client = Google::APIClient.new
- # flow = Google::APIClient::InstalledAppFlow.new(
- # :client_id => '691380668085.apps.googleusercontent.com',
- # :client_secret => '...',
- # :scope => 'https://www.googleapis.com/auth/drive'
- # )
- # client.authorization = flow.authorize
- #
- class InstalledAppFlow
-
- RESPONSE_BODY = <<-HTML
-
-
-
-
- You may close this window.
-
- HTML
-
- ##
- # Configure the flow
- #
- # @param [Hash] options The configuration parameters for the client.
- # @option options [Fixnum] :port
- # Port to run the embedded server on. Defaults to 9292
- # @option options [String] :client_id
- # A unique identifier issued to the client to identify itself to the
- # authorization server.
- # @option options [String] :client_secret
- # A shared symmetric secret issued by the authorization server,
- # which is used to authenticate the client.
- # @option options [String] :scope
- # The scope of the access request, expressed either as an Array
- # or as a space-delimited String.
- #
- # @see Signet::OAuth2::Client
- def initialize(options)
- @port = options[:port] || 9292
- @authorization = Signet::OAuth2::Client.new({
- :authorization_uri => 'https://accounts.google.com/o/oauth2/auth',
- :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
- :redirect_uri => "http://localhost:#{@port}/"}.update(options)
- )
- end
-
- ##
- # Request authorization. Opens a browser and waits for response.
- #
- # @param [Google::APIClient::Storage] storage
- # Optional object that responds to :write_credentials, used to serialize
- # the OAuth 2 credentials after completing the flow.
- #
- # @return [Signet::OAuth2::Client]
- # Authorization instance, nil if user cancelled.
- def authorize(storage=nil)
- auth = @authorization
-
- server = WEBrick::HTTPServer.new(
- :Port => @port,
- :BindAddress =>"localhost",
- :Logger => WEBrick::Log.new(STDOUT, 0),
- :AccessLog => []
- )
- begin
- trap("INT") { server.shutdown }
-
- server.mount_proc '/' do |req, res|
- auth.code = req.query['code']
- if auth.code
- auth.fetch_access_token!
- end
- res.status = WEBrick::HTTPStatus::RC_ACCEPTED
- res.body = RESPONSE_BODY
- server.stop
- end
-
- Launchy.open(auth.authorization_uri.to_s)
- server.start
- ensure
- server.shutdown
- end
- if @authorization.access_token
- if storage.respond_to?(:write_credentials)
- storage.write_credentials(@authorization)
- end
- return @authorization
- else
- return nil
- end
- end
- end
-
- end
-end
-
diff --git a/lib/google/api_client/auth/jwt_asserter.rb b/lib/google/api_client/auth/jwt_asserter.rb
deleted file mode 100644
index 35ad6ec8ea9..00000000000
--- a/lib/google/api_client/auth/jwt_asserter.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'jwt'
-require 'signet/oauth_2/client'
-require 'delegate'
-
-module Google
- class APIClient
- ##
- # Generates access tokens using the JWT assertion profile. Requires a
- # service account & access to the private key.
- #
- # @example Using Signet
- #
- # key = Google::APIClient::KeyUtils.load_from_pkcs12('client.p12', 'notasecret')
- # client.authorization = Signet::OAuth2::Client.new(
- # :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
- # :audience => 'https://accounts.google.com/o/oauth2/token',
- # :scope => 'https://www.googleapis.com/auth/prediction',
- # :issuer => '123456-abcdef@developer.gserviceaccount.com',
- # :signing_key => key)
- # client.authorization.fetch_access_token!
- # client.execute(...)
- #
- # @deprecated
- # Service accounts are now supported directly in Signet
- # @see https://developers.google.com/accounts/docs/OAuth2ServiceAccount
- class JWTAsserter
- # @return [String] ID/email of the issuing party
- attr_accessor :issuer
- # @return [Fixnum] How long, in seconds, the assertion is valid for
- attr_accessor :expiry
- # @return [Fixnum] Seconds to expand the issued at/expiry window to account for clock skew
- attr_accessor :skew
- # @return [String] Scopes to authorize
- attr_reader :scope
- # @return [String,OpenSSL::PKey] key for signing assertions
- attr_writer :key
- # @return [String] Algorithm used for signing
- attr_accessor :algorithm
-
- ##
- # Initializes the asserter for a service account.
- #
- # @param [String] issuer
- # Name/ID of the client issuing the assertion
- # @param [String, Array] scope
- # Scopes to authorize. May be a space delimited string or array of strings
- # @param [String,OpenSSL::PKey] key
- # Key for signing assertions
- # @param [String] algorithm
- # Algorithm to use, either 'RS256' for RSA with SHA-256
- # or 'HS256' for HMAC with SHA-256
- def initialize(issuer, scope, key, algorithm = "RS256")
- self.issuer = issuer
- self.scope = scope
- self.expiry = 60 # 1 min default
- self.skew = 60
- self.key = key
- self.algorithm = algorithm
- end
-
- ##
- # Set the scopes to authorize
- #
- # @param [String, Array] new_scope
- # Scopes to authorize. May be a space delimited string or array of strings
- def scope=(new_scope)
- case new_scope
- when Array
- @scope = new_scope.join(' ')
- when String
- @scope = new_scope
- when nil
- @scope = ''
- else
- raise TypeError, "Expected Array or String, got #{new_scope.class}"
- end
- end
-
- ##
- # Request a new access token.
- #
- # @param [String] person
- # Email address of a user, if requesting a token to act on their behalf
- # @param [Hash] options
- # Pass through to Signet::OAuth2::Client.fetch_access_token
- # @return [Signet::OAuth2::Client] Access token
- #
- # @see Signet::OAuth2::Client.fetch_access_token!
- def authorize(person = nil, options={})
- authorization = self.to_authorization(person)
- authorization.fetch_access_token!(options)
- return authorization
- end
-
- ##
- # Builds a Signet OAuth2 client
- #
- # @return [Signet::OAuth2::Client] Access token
- def to_authorization(person = nil)
- return Signet::OAuth2::Client.new(
- :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
- :audience => 'https://accounts.google.com/o/oauth2/token',
- :scope => self.scope,
- :issuer => @issuer,
- :signing_key => @key,
- :signing_algorithm => @algorithm,
- :person => person
- )
- end
- end
- end
-end
diff --git a/lib/google/api_client/auth/key_utils.rb b/lib/google/api_client/auth/key_utils.rb
deleted file mode 100644
index 6b6e0cfe5f8..00000000000
--- a/lib/google/api_client/auth/key_utils.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-module Google
- class APIClient
- ##
- # Helper for loading keys from the PKCS12 files downloaded when
- # setting up service accounts at the APIs Console.
- #
- module KeyUtils
- ##
- # Loads a key from PKCS12 file, assuming a single private key
- # is present.
- #
- # @param [String] keyfile
- # Path of the PKCS12 file to load. If not a path to an actual file,
- # assumes the string is the content of the file itself.
- # @param [String] passphrase
- # Passphrase for unlocking the private key
- #
- # @return [OpenSSL::PKey] The private key for signing assertions.
- def self.load_from_pkcs12(keyfile, passphrase)
- load_key(keyfile, passphrase) do |content, pass_phrase|
- OpenSSL::PKCS12.new(content, pass_phrase).key
- end
- end
-
-
- ##
- # Loads a key from a PEM file.
- #
- # @param [String] keyfile
- # Path of the PEM file to load. If not a path to an actual file,
- # assumes the string is the content of the file itself.
- # @param [String] passphrase
- # Passphrase for unlocking the private key
- #
- # @return [OpenSSL::PKey] The private key for signing assertions.
- #
- def self.load_from_pem(keyfile, passphrase)
- load_key(keyfile, passphrase) do | content, pass_phrase|
- OpenSSL::PKey::RSA.new(content, pass_phrase)
- end
- end
-
- private
-
- ##
- # Helper for loading keys from file or memory. Accepts a block
- # to handle the specific file format.
- #
- # @param [String] keyfile
- # Path of thefile to load. If not a path to an actual file,
- # assumes the string is the content of the file itself.
- # @param [String] passphrase
- # Passphrase for unlocking the private key
- #
- # @yield [String, String]
- # Key file & passphrase to extract key from
- # @yieldparam [String] keyfile
- # Contents of the file
- # @yieldparam [String] passphrase
- # Passphrase to unlock key
- # @yieldreturn [OpenSSL::PKey]
- # Private key
- #
- # @return [OpenSSL::PKey] The private key for signing assertions.
- def self.load_key(keyfile, passphrase, &block)
- begin
- begin
- content = File.open(keyfile, 'rb') { |io| io.read }
- rescue
- content = keyfile
- end
- block.call(content, passphrase)
- rescue OpenSSL::OpenSSLError
- raise ArgumentError.new("Invalid keyfile or passphrase")
- end
- end
- end
- end
-end
diff --git a/lib/google/api_client/auth/pkcs12.rb b/lib/google/api_client/auth/pkcs12.rb
deleted file mode 100644
index 94c43185dbd..00000000000
--- a/lib/google/api_client/auth/pkcs12.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'google/api_client/auth/key_utils'
-module Google
- class APIClient
- ##
- # Helper for loading keys from the PKCS12 files downloaded when
- # setting up service accounts at the APIs Console.
- #
- module PKCS12
- ##
- # Loads a key from PKCS12 file, assuming a single private key
- # is present.
- #
- # @param [String] keyfile
- # Path of the PKCS12 file to load. If not a path to an actual file,
- # assumes the string is the content of the file itself.
- # @param [String] passphrase
- # Passphrase for unlocking the private key
- #
- # @return [OpenSSL::PKey] The private key for signing assertions.
- # @deprecated
- # Use {Google::APIClient::KeyUtils} instead
- def self.load_key(keyfile, passphrase)
- KeyUtils.load_from_pkcs12(keyfile, passphrase)
- end
- end
- end
-end
diff --git a/lib/google/api_client/auth/storage.rb b/lib/google/api_client/auth/storage.rb
deleted file mode 100644
index c762316e754..00000000000
--- a/lib/google/api_client/auth/storage.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# Copyright 2013 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'signet/oauth_2/client'
-
-module Google
- class APIClient
- ##
- # Represents cached OAuth 2 tokens stored on local disk in a
- # JSON serialized file. Meant to resemble the serialized format
- # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
- #
- class Storage
-
- AUTHORIZATION_URI = 'https://accounts.google.com/o/oauth2/auth'
- TOKEN_CREDENTIAL_URI = 'https://accounts.google.com/o/oauth2/token'
-
- # @return [Object] Storage object.
- attr_accessor :store
-
- # @return [Signet::OAuth2::Client]
- attr_reader :authorization
-
- ##
- # Initializes the Storage object.
- #
- # @params [Object] Storage object
- def initialize(store)
- @store= store
- @authorization = nil
- end
-
- ##
- # Write the credentials to the specified store.
- #
- # @params [Signet::OAuth2::Client] authorization
- # Optional authorization instance. If not provided, the authorization
- # already associated with this instance will be written.
- def write_credentials(authorization=nil)
- @authorization = authorization if authorization
- if @authorization.respond_to?(:refresh_token) && @authorization.refresh_token
- store.write_credentials(credentials_hash)
- end
- end
-
- ##
- # Loads credentials and authorizes an client.
- # @return [Object] Signet::OAuth2::Client or NIL
- def authorize
- @authorization = nil
- cached_credentials = load_credentials
- if cached_credentials && cached_credentials.size > 0
- @authorization = Signet::OAuth2::Client.new(cached_credentials)
- @authorization.issued_at = Time.at(cached_credentials['issued_at'].to_i)
- self.refresh_authorization if @authorization.expired?
- end
- return @authorization
- end
-
- ##
- # refresh credentials and save them to store
- def refresh_authorization
- authorization.refresh!
- self.write_credentials
- end
-
- private
-
- ##
- # Attempt to read in credentials from the specified store.
- def load_credentials
- store.load_credentials
- end
-
- ##
- # @return [Hash] with credentials
- def credentials_hash
- {
- :access_token => authorization.access_token,
- :authorization_uri => AUTHORIZATION_URI,
- :client_id => authorization.client_id,
- :client_secret => authorization.client_secret,
- :expires_in => authorization.expires_in,
- :refresh_token => authorization.refresh_token,
- :token_credential_uri => TOKEN_CREDENTIAL_URI,
- :issued_at => authorization.issued_at.to_i
- }
- end
- end
- end
-end
diff --git a/lib/google/api_client/auth/storages/file_store.rb b/lib/google/api_client/auth/storages/file_store.rb
deleted file mode 100644
index cd3eae710d9..00000000000
--- a/lib/google/api_client/auth/storages/file_store.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright 2013 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'json'
-
-module Google
- class APIClient
- ##
- # Represents cached OAuth 2 tokens stored on local disk in a
- # JSON serialized file. Meant to resemble the serialized format
- # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
- #
- class FileStore
-
- attr_accessor :path
-
- ##
- # Initializes the FileStorage object.
- #
- # @param [String] path
- # Path to the credentials file.
- def initialize(path)
- @path= path
- end
-
- ##
- # Attempt to read in credentials from the specified file.
- def load_credentials
- open(path, 'r') { |f| JSON.parse(f.read) }
- rescue
- nil
- end
-
- ##
- # Write the credentials to the specified file.
- #
- # @param [Signet::OAuth2::Client] authorization
- # Optional authorization instance. If not provided, the authorization
- # already associated with this instance will be written.
- def write_credentials(credentials_hash)
- open(self.path, 'w+') do |f|
- f.write(credentials_hash.to_json)
- end
- end
- end
- end
-end
diff --git a/lib/google/api_client/auth/storages/redis_store.rb b/lib/google/api_client/auth/storages/redis_store.rb
deleted file mode 100644
index 3f76f7ca860..00000000000
--- a/lib/google/api_client/auth/storages/redis_store.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright 2013 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'json'
-
-module Google
- class APIClient
- class RedisStore
-
- DEFAULT_REDIS_CREDENTIALS_KEY = "google_api_credentials"
-
- attr_accessor :redis
-
- ##
- # Initializes the RedisStore object.
- #
- # @params [Object] Redis instance
- def initialize(redis, key = nil)
- @redis= redis
- @redis_credentials_key = key
- end
-
- ##
- # Attempt to read in credentials from redis.
- def load_credentials
- credentials = redis.get redis_credentials_key
- JSON.parse(credentials) if credentials
- end
-
- def redis_credentials_key
- @redis_credentials_key || DEFAULT_REDIS_CREDENTIALS_KEY
- end
-
- ##
- # Write the credentials to redis.
- #
- # @params [Hash] credentials
- def write_credentials(credentials_hash)
- redis.set(redis_credentials_key, credentials_hash.to_json)
- end
- end
- end
-end
diff --git a/lib/google/api_client/batch.rb b/lib/google/api_client/batch.rb
deleted file mode 100644
index 45a2e31044e..00000000000
--- a/lib/google/api_client/batch.rb
+++ /dev/null
@@ -1,326 +0,0 @@
-# Copyright 2012 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'addressable/uri'
-require 'google/api_client/reference'
-require 'securerandom'
-
-module Google
- class APIClient
-
- ##
- # Helper class to contain a response to an individual batched call.
- #
- # @api private
- class BatchedCallResponse
- # @return [String] UUID of the call
- attr_reader :call_id
- # @return [Fixnum] HTTP status code
- attr_accessor :status
- # @return [Hash] HTTP response headers
- attr_accessor :headers
- # @return [String] HTTP response body
- attr_accessor :body
-
- ##
- # Initialize the call response
- #
- # @param [String] call_id
- # UUID of the original call
- # @param [Fixnum] status
- # HTTP status
- # @param [Hash] headers
- # HTTP response headers
- # @param [#read, #to_str] body
- # Response body
- def initialize(call_id, status = nil, headers = nil, body = nil)
- @call_id, @status, @headers, @body = call_id, status, headers, body
- end
- end
-
- # Wraps multiple API calls into a single over-the-wire HTTP request.
- #
- # @example
- #
- # client = Google::APIClient.new
- # urlshortener = client.discovered_api('urlshortener')
- # batch = Google::APIClient::BatchRequest.new do |result|
- # puts result.data
- # end
- #
- # batch.add(:api_method => urlshortener.url.insert, :body_object => { 'longUrl' => 'http://example.com/foo' })
- # batch.add(:api_method => urlshortener.url.insert, :body_object => { 'longUrl' => 'http://example.com/bar' })
- #
- # client.execute(batch)
- #
- class BatchRequest < Request
- BATCH_BOUNDARY = "-----------RubyApiBatchRequest".freeze
-
- # @api private
- # @return [Array<(String,Google::APIClient::Request,Proc)] List of API calls in the batch
- attr_reader :calls
-
- ##
- # Creates a new batch request.
- #
- # @param [Hash] options
- # Set of options for this request.
- # @param [Proc] block
- # Callback for every call's response. Won't be called if a call defined
- # a callback of its own.
- #
- # @return [Google::APIClient::BatchRequest]
- # The constructed object.
- #
- # @yield [Google::APIClient::Result]
- # block to be called when result ready
- def initialize(options = {}, &block)
- @calls = []
- @global_callback = nil
- @global_callback = block if block_given?
- @last_auto_id = 0
-
- @base_id = SecureRandom.uuid
-
- options[:uri] ||= 'https://www.googleapis.com/batch'
- options[:http_method] ||= 'POST'
-
- super options
- end
-
- ##
- # Add a new call to the batch request.
- # Each call must have its own call ID; if not provided, one will
- # automatically be generated, avoiding collisions. If duplicate call IDs
- # are provided, an error will be thrown.
- #
- # @param [Hash, Google::APIClient::Request] call
- # the call to be added.
- # @param [String] call_id
- # the ID to be used for this call. Must be unique
- # @param [Proc] block
- # callback for this call's response.
- #
- # @return [Google::APIClient::BatchRequest]
- # the BatchRequest, for chaining
- #
- # @yield [Google::APIClient::Result]
- # block to be called when result ready
- def add(call, call_id = nil, &block)
- unless call.kind_of?(Google::APIClient::Reference)
- call = Google::APIClient::Reference.new(call)
- end
- call_id ||= new_id
- if @calls.assoc(call_id)
- raise BatchError,
- 'A call with this ID already exists: %s' % call_id
- end
- callback = block_given? ? block : @global_callback
- @calls << [call_id, call, callback]
- return self
- end
-
- ##
- # Processes the HTTP response to the batch request, issuing callbacks.
- #
- # @api private
- #
- # @param [Faraday::Response] response
- # the HTTP response.
- def process_http_response(response)
- content_type = find_header('Content-Type', response.headers)
- m = /.*boundary=(.+)/.match(content_type)
- if m
- boundary = m[1]
- parts = response.body.split(/--#{Regexp.escape(boundary)}/)
- parts = parts[1...-1]
- parts.each do |part|
- call_response = deserialize_call_response(part)
- _, call, callback = @calls.assoc(call_response.call_id)
- result = Google::APIClient::Result.new(call, call_response)
- callback.call(result) if callback
- end
- end
- Google::APIClient::Result.new(self, response)
- end
-
- ##
- # Return the request body for the BatchRequest's HTTP request.
- #
- # @api private
- #
- # @return [String]
- # the request body.
- def to_http_request
- if @calls.nil? || @calls.empty?
- raise BatchError, 'Cannot make an empty batch request'
- end
- parts = @calls.map {|(call_id, call, _callback)| serialize_call(call_id, call)}
- build_multipart(parts, 'multipart/mixed', BATCH_BOUNDARY)
- super
- end
-
-
- protected
-
- ##
- # Helper method to find a header from its name, regardless of case.
- #
- # @api private
- #
- # @param [String] name
- # the name of the header to find.
- # @param [Hash] headers
- # the hash of headers and their values.
- #
- # @return [String]
- # the value of the desired header.
- def find_header(name, headers)
- _, header = headers.detect do |h, v|
- h.downcase == name.downcase
- end
- return header
- end
-
- ##
- # Create a new call ID. Uses an auto-incrementing, conflict-avoiding ID.
- #
- # @api private
- #
- # @return [String]
- # the new, unique ID.
- def new_id
- @last_auto_id += 1
- while @calls.assoc(@last_auto_id)
- @last_auto_id += 1
- end
- return @last_auto_id.to_s
- end
-
- ##
- # Convert a Content-ID header value to an id. Presumes the Content-ID
- # header conforms to the format that id_to_header() returns.
- #
- # @api private
- #
- # @param [String] header
- # Content-ID header value.
- #
- # @return [String]
- # The extracted ID value.
- def header_to_id(header)
- if !header.start_with?('<') || !header.end_with?('>') ||
- !header.include?('+')
- raise BatchError, 'Invalid value for Content-ID: "%s"' % header
- end
-
- _base, call_id = header[1...-1].split('+')
- return Addressable::URI.unencode(call_id)
- end
-
- ##
- # Auxiliary method to split the headers from the body in an HTTP response.
- #
- # @api private
- #
- # @param [String] response
- # the response to parse.
- #
- # @return [Array, String]
- # the headers and the body, separately.
- def split_headers_and_body(response)
- headers = {}
- payload = response.lstrip
- while payload
- line, payload = payload.split("\n", 2)
- line.sub!(/\s+\z/, '')
- break if line.empty?
- match = /\A([^:]+):\s*/.match(line)
- if match
- headers[match[1]] = match.post_match
- else
- raise BatchError, 'Invalid header line in response: %s' % line
- end
- end
- return headers, payload
- end
-
- ##
- # Convert a single batched response into a BatchedCallResponse object.
- #
- # @api private
- #
- # @param [String] call_response
- # the request to deserialize.
- #
- # @return [Google::APIClient::BatchedCallResponse]
- # the parsed and converted response.
- def deserialize_call_response(call_response)
- outer_headers, outer_body = split_headers_and_body(call_response)
- status_line, payload = outer_body.split("\n", 2)
- _protocol, status, _reason = status_line.split(' ', 3)
-
- headers, body = split_headers_and_body(payload)
- content_id = find_header('Content-ID', outer_headers)
- call_id = header_to_id(content_id)
- return BatchedCallResponse.new(call_id, status.to_i, headers, body)
- end
-
- ##
- # Serialize a single batched call for assembling the multipart message
- #
- # @api private
- #
- # @param [Google::APIClient::Request] call
- # the call to serialize.
- #
- # @return [Faraday::UploadIO]
- # the serialized request
- def serialize_call(call_id, call)
- method, uri, headers, body = call.to_http_request
- request = "#{method.to_s.upcase} #{Addressable::URI.parse(uri).request_uri} HTTP/1.1"
- headers.each do |header, value|
- request << "\r\n%s: %s" % [header, value]
- end
- if body
- # TODO - CompositeIO if body is a stream
- request << "\r\n\r\n"
- if body.respond_to?(:read)
- request << body.read
- else
- request << body.to_s
- end
- end
- Faraday::UploadIO.new(StringIO.new(request), 'application/http', 'ruby-api-request', 'Content-ID' => id_to_header(call_id))
- end
-
- ##
- # Convert an id to a Content-ID header value.
- #
- # @api private
- #
- # @param [String] call_id
- # identifier of individual call.
- #
- # @return [String]
- # A Content-ID header with the call_id encoded into it. A UUID is
- # prepended to the value because Content-ID headers are supposed to be
- # universally unique.
- def id_to_header(call_id)
- return '<%s+%s>' % [@base_id, Addressable::URI.encode(call_id)]
- end
-
- end
- end
-end
\ No newline at end of file
diff --git a/lib/google/api_client/charset.rb b/lib/google/api_client/charset.rb
deleted file mode 100644
index 47b11ba841f..00000000000
--- a/lib/google/api_client/charset.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require 'faraday'
-require 'zlib'
-
-module Google
- class APIClient
- class Charset < Faraday::Response::Middleware
- include Google::APIClient::Logging
-
- def charset_for_content_type(type)
- if type
- m = type.match(/(?:charset|encoding)="?([a-z0-9-]+)"?/i)
- if m
- return Encoding.find(m[1])
- end
- end
- nil
- end
-
- def adjust_encoding(env)
- charset = charset_for_content_type(env[:response_headers]['content-type'])
- if charset && env[:body].encoding != charset
- env[:body].force_encoding(charset)
- end
- end
-
- def on_complete(env)
- adjust_encoding(env)
- end
- end
- end
-end
-
-Faraday::Response.register_middleware :charset => Google::APIClient::Charset
\ No newline at end of file
diff --git a/lib/google/api_client/client_secrets.rb b/lib/google/api_client/client_secrets.rb
deleted file mode 100644
index a9cc2413896..00000000000
--- a/lib/google/api_client/client_secrets.rb
+++ /dev/null
@@ -1,179 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-require 'compat/multi_json'
-
-
-module Google
- class APIClient
- ##
- # Manages the persistence of client configuration data and secrets. Format
- # inspired by the Google API Python client.
- #
- # @see https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
- #
- # @example
- # {
- # "web": {
- # "client_id": "asdfjasdljfasdkjf",
- # "client_secret": "1912308409123890",
- # "redirect_uris": ["https://www.example.com/oauth2callback"],
- # "auth_uri": "https://accounts.google.com/o/oauth2/auth",
- # "token_uri": "https://accounts.google.com/o/oauth2/token"
- # }
- # }
- #
- # @example
- # {
- # "installed": {
- # "client_id": "837647042410-75ifg...usercontent.com",
- # "client_secret":"asdlkfjaskd",
- # "redirect_uris": ["http://localhost", "urn:ietf:oauth:2.0:oob"],
- # "auth_uri": "https://accounts.google.com/o/oauth2/auth",
- # "token_uri": "https://accounts.google.com/o/oauth2/token"
- # }
- # }
- class ClientSecrets
-
- ##
- # Reads client configuration from a file
- #
- # @param [String] filename
- # Path to file to load
- #
- # @return [Google::APIClient::ClientSecrets]
- # OAuth client settings
- def self.load(filename=nil)
- if filename && File.directory?(filename)
- search_path = File.expand_path(filename)
- filename = nil
- end
- while filename == nil
- search_path ||= File.expand_path('.')
- if File.exists?(File.join(search_path, 'client_secrets.json'))
- filename = File.join(search_path, 'client_secrets.json')
- elsif search_path == '/' || search_path =~ /[a-zA-Z]:[\/\\]/
- raise ArgumentError,
- 'No client_secrets.json filename supplied ' +
- 'and/or could not be found in search path.'
- else
- search_path = File.expand_path(File.join(search_path, '..'))
- end
- end
- data = File.open(filename, 'r') { |file| MultiJson.load(file.read) }
- return self.new(data)
- end
-
- ##
- # Intialize OAuth client settings.
- #
- # @param [Hash] options
- # Parsed client secrets files
- def initialize(options={})
- # Client auth configuration
- @flow = options[:flow] || options.keys.first.to_s || 'web'
- fdata = options[@flow]
- @client_id = fdata[:client_id] || fdata["client_id"]
- @client_secret = fdata[:client_secret] || fdata["client_secret"]
- @redirect_uris = fdata[:redirect_uris] || fdata["redirect_uris"]
- @redirect_uris ||= [fdata[:redirect_uri] || fdata["redirect_uri"]].compact
- @javascript_origins = (
- fdata[:javascript_origins] ||
- fdata["javascript_origins"]
- )
- @javascript_origins ||= [fdata[:javascript_origin] || fdata["javascript_origin"]].compact
- @authorization_uri = fdata[:auth_uri] || fdata["auth_uri"]
- @authorization_uri ||= fdata[:authorization_uri]
- @token_credential_uri = fdata[:token_uri] || fdata["token_uri"]
- @token_credential_uri ||= fdata[:token_credential_uri]
-
- # Associated token info
- @access_token = fdata[:access_token] || fdata["access_token"]
- @refresh_token = fdata[:refresh_token] || fdata["refresh_token"]
- @id_token = fdata[:id_token] || fdata["id_token"]
- @expires_in = fdata[:expires_in] || fdata["expires_in"]
- @expires_at = fdata[:expires_at] || fdata["expires_at"]
- @issued_at = fdata[:issued_at] || fdata["issued_at"]
- end
-
- attr_reader(
- :flow, :client_id, :client_secret, :redirect_uris, :javascript_origins,
- :authorization_uri, :token_credential_uri, :access_token,
- :refresh_token, :id_token, :expires_in, :expires_at, :issued_at
- )
-
- ##
- # Serialize back to the original JSON form
- #
- # @return [String]
- # JSON
- def to_json
- return MultiJson.dump(to_hash)
- end
-
- def to_hash
- {
- self.flow => ({
- 'client_id' => self.client_id,
- 'client_secret' => self.client_secret,
- 'redirect_uris' => self.redirect_uris,
- 'javascript_origins' => self.javascript_origins,
- 'auth_uri' => self.authorization_uri,
- 'token_uri' => self.token_credential_uri,
- 'access_token' => self.access_token,
- 'refresh_token' => self.refresh_token,
- 'id_token' => self.id_token,
- 'expires_in' => self.expires_in,
- 'expires_at' => self.expires_at,
- 'issued_at' => self.issued_at
- }).inject({}) do |accu, (k, v)|
- # Prunes empty values from JSON output.
- unless v == nil || (v.respond_to?(:empty?) && v.empty?)
- accu[k] = v
- end
- accu
- end
- }
- end
-
- def to_authorization
- gem 'signet', '>= 0.4.0'
- require 'signet/oauth_2/client'
- # NOTE: Do not rely on this default value, as it may change
- new_authorization = Signet::OAuth2::Client.new
- new_authorization.client_id = self.client_id
- new_authorization.client_secret = self.client_secret
- new_authorization.authorization_uri = (
- self.authorization_uri ||
- 'https://accounts.google.com/o/oauth2/auth'
- )
- new_authorization.token_credential_uri = (
- self.token_credential_uri ||
- 'https://accounts.google.com/o/oauth2/token'
- )
- new_authorization.redirect_uri = self.redirect_uris.first
-
- # These are supported, but unlikely.
- new_authorization.access_token = self.access_token
- new_authorization.refresh_token = self.refresh_token
- new_authorization.id_token = self.id_token
- new_authorization.expires_in = self.expires_in
- new_authorization.issued_at = self.issued_at if self.issued_at
- new_authorization.expires_at = self.expires_at if self.expires_at
- return new_authorization
- end
- end
- end
-end
diff --git a/lib/google/api_client/discovery/api.rb b/lib/google/api_client/discovery/api.rb
deleted file mode 100644
index 3bbc90da3f3..00000000000
--- a/lib/google/api_client/discovery/api.rb
+++ /dev/null
@@ -1,310 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-require 'addressable/uri'
-require 'multi_json'
-require 'active_support/inflector'
-require 'google/api_client/discovery/resource'
-require 'google/api_client/discovery/method'
-require 'google/api_client/discovery/media'
-
-module Google
- class APIClient
- ##
- # A service that has been described by a discovery document.
- class API
-
- ##
- # Creates a description of a particular version of a service.
- #
- # @param [String] document_base
- # Base URI for the discovery document.
- # @param [Hash] discovery_document
- # The section of the discovery document that applies to this service
- # version.
- #
- # @return [Google::APIClient::API] The constructed service object.
- def initialize(document_base, discovery_document)
- @document_base = Addressable::URI.parse(document_base)
- @discovery_document = discovery_document
- metaclass = (class << self; self; end)
- self.discovered_resources.each do |resource|
- method_name = ActiveSupport::Inflector.underscore(resource.name).to_sym
- if !self.respond_to?(method_name)
- metaclass.send(:define_method, method_name) { resource }
- end
- end
- self.discovered_methods.each do |method|
- method_name = ActiveSupport::Inflector.underscore(method.name).to_sym
- if !self.respond_to?(method_name)
- metaclass.send(:define_method, method_name) { method }
- end
- end
- end
-
- # @return [String] unparsed discovery document for the API
- attr_reader :discovery_document
-
- ##
- # Returns the id of the service.
- #
- # @return [String] The service id.
- def id
- return (
- @discovery_document['id'] ||
- "#{self.name}:#{self.version}"
- )
- end
-
- ##
- # Returns the identifier for the service.
- #
- # @return [String] The service identifier.
- def name
- return @discovery_document['name']
- end
-
- ##
- # Returns the version of the service.
- #
- # @return [String] The service version.
- def version
- return @discovery_document['version']
- end
-
- ##
- # Returns a human-readable title for the API.
- #
- # @return [Hash] The API title.
- def title
- return @discovery_document['title']
- end
-
- ##
- # Returns a human-readable description of the API.
- #
- # @return [Hash] The API description.
- def description
- return @discovery_document['description']
- end
-
- ##
- # Returns a URI for the API documentation.
- #
- # @return [Hash] The API documentation.
- def documentation
- return Addressable::URI.parse(@discovery_document['documentationLink'])
- end
-
- ##
- # Returns true if this is the preferred version of this API.
- #
- # @return [TrueClass, FalseClass]
- # Whether or not this is the preferred version of this API.
- def preferred
- return !!@discovery_document['preferred']
- end
-
- ##
- # Returns the list of API features.
- #
- # @return [Array]
- # The features supported by this API.
- def features
- return @discovery_document['features'] || []
- end
-
- ##
- # Returns the root URI for this service.
- #
- # @return [Addressable::URI] The root URI.
- def root_uri
- return @root_uri ||= (
- Addressable::URI.parse(self.discovery_document['rootUrl'])
- )
- end
-
- ##
- # Returns true if this API uses a data wrapper.
- #
- # @return [TrueClass, FalseClass]
- # Whether or not this API uses a data wrapper.
- def data_wrapper?
- return self.features.include?('dataWrapper')
- end
-
- ##
- # Returns the base URI for the discovery document.
- #
- # @return [Addressable::URI] The base URI.
- attr_reader :document_base
-
- ##
- # Returns the base URI for this version of the service.
- #
- # @return [Addressable::URI] The base URI that methods are joined to.
- def method_base
- if @discovery_document['basePath']
- return @method_base ||= (
- self.root_uri.join(Addressable::URI.parse(@discovery_document['basePath']))
- ).normalize
- else
- return nil
- end
- end
-
- ##
- # Updates the hierarchy of resources and methods with the new base.
- #
- # @param [Addressable::URI, #to_str, String] new_method_base
- # The new base URI to use for the service.
- def method_base=(new_method_base)
- @method_base = Addressable::URI.parse(new_method_base)
- self.discovered_resources.each do |resource|
- resource.method_base = @method_base
- end
- self.discovered_methods.each do |method|
- method.method_base = @method_base
- end
- end
-
- ##
- # Returns the base URI for batch calls to this service.
- #
- # @return [Addressable::URI] The base URI that methods are joined to.
- def batch_path
- if @discovery_document['batchPath']
- return @batch_path ||= (
- self.document_base.join(Addressable::URI.parse('/' +
- @discovery_document['batchPath']))
- ).normalize
- else
- return nil
- end
- end
-
- ##
- # A list of schemas available for this version of the API.
- #
- # @return [Hash] A list of {Google::APIClient::Schema} objects.
- def schemas
- return @schemas ||= (
- (@discovery_document['schemas'] || []).inject({}) do |accu, (k, v)|
- accu[k] = Google::APIClient::Schema.parse(self, v)
- accu
- end
- )
- end
-
- ##
- # Returns a schema for a kind value.
- #
- # @return [Google::APIClient::Schema] The associated Schema object.
- def schema_for_kind(kind)
- api_name, schema_name = kind.split('#', 2)
- if api_name != self.name
- raise ArgumentError,
- "The kind does not match this API. " +
- "Expected '#{self.name}', got '#{api_name}'."
- end
- for k, v in self.schemas
- return v if k.downcase == schema_name.downcase
- end
- return nil
- end
-
- ##
- # A list of resources available at the root level of this version of the
- # API.
- #
- # @return [Array] A list of {Google::APIClient::Resource} objects.
- def discovered_resources
- return @discovered_resources ||= (
- (@discovery_document['resources'] || []).inject([]) do |accu, (k, v)|
- accu << Google::APIClient::Resource.new(
- self, self.method_base, k, v
- )
- accu
- end
- )
- end
-
- ##
- # A list of methods available at the root level of this version of the
- # API.
- #
- # @return [Array] A list of {Google::APIClient::Method} objects.
- def discovered_methods
- return @discovered_methods ||= (
- (@discovery_document['methods'] || []).inject([]) do |accu, (k, v)|
- accu << Google::APIClient::Method.new(self, self.method_base, k, v)
- accu
- end
- )
- end
-
- ##
- # Allows deep inspection of the discovery document.
- def [](key)
- return @discovery_document[key]
- end
-
- ##
- # Converts the service to a flat mapping of RPC names and method objects.
- #
- # @return [Hash] All methods available on the service.
- #
- # @example
- # # Discover available methods
- # method_names = client.discovered_api('buzz').to_h.keys
- def to_h
- return @hash ||= (begin
- methods_hash = {}
- self.discovered_methods.each do |method|
- methods_hash[method.id] = method
- end
- self.discovered_resources.each do |resource|
- methods_hash.merge!(resource.to_h)
- end
- methods_hash
- end)
- end
-
- ##
- # Returns a String representation of the service's state.
- #
- # @return [String] The service's state, as a String.
- def inspect
- sprintf(
- "#<%s:%#0x ID:%s>", self.class.to_s, self.object_id, self.id
- )
- end
-
- ##
- # Marshalling support - serialize the API to a string (doc base + original
- # discovery document).
- def _dump(level)
- MultiJson.dump([@document_base.to_s, @discovery_document])
- end
-
- ##
- # Marshalling support - Restore an API instance from serialized form
- def self._load(obj)
- new(*MultiJson.load(obj))
- end
-
- end
- end
-end
diff --git a/lib/google/api_client/discovery/media.rb b/lib/google/api_client/discovery/media.rb
deleted file mode 100644
index ffa7e87c3db..00000000000
--- a/lib/google/api_client/discovery/media.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-require 'addressable/uri'
-require 'addressable/template'
-
-require 'google/api_client/errors'
-
-
-module Google
- class APIClient
- ##
- # Media upload elements for discovered methods
- class MediaUpload
-
- ##
- # Creates a description of a particular method.
- #
- # @param [Google::APIClient::API] api
- # Base discovery document for the API
- # @param [Addressable::URI] method_base
- # The base URI for the service.
- # @param [Hash] discovery_document
- # The media upload section of the discovery document.
- #
- # @return [Google::APIClient::Method] The constructed method object.
- def initialize(api, method_base, discovery_document)
- @api = api
- @method_base = method_base
- @discovery_document = discovery_document
- end
-
- ##
- # List of acceptable mime types
- #
- # @return [Array]
- # List of acceptable mime types for uploaded content
- def accepted_types
- @discovery_document['accept']
- end
-
- ##
- # Maximum size of an uplad
- # TODO: Parse & convert to numeric value
- #
- # @return [String]
- def max_size
- @discovery_document['maxSize']
- end
-
- ##
- # Returns the URI template for the method. A parameter list can be
- # used to expand this into a URI.
- #
- # @return [Addressable::Template] The URI template.
- def uri_template
- return @uri_template ||= Addressable::Template.new(
- @api.method_base.join(Addressable::URI.parse(@discovery_document['protocols']['simple']['path']))
- )
- end
-
- end
-
- end
-end
diff --git a/lib/google/api_client/discovery/method.rb b/lib/google/api_client/discovery/method.rb
deleted file mode 100644
index 3a06857c0e3..00000000000
--- a/lib/google/api_client/discovery/method.rb
+++ /dev/null
@@ -1,363 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-require 'addressable/uri'
-require 'addressable/template'
-
-require 'google/api_client/errors'
-
-
-module Google
- class APIClient
- ##
- # A method that has been described by a discovery document.
- class Method
-
- ##
- # Creates a description of a particular method.
- #
- # @param [Google::APIClient::API] api
- # The API this method belongs to.
- # @param [Addressable::URI] method_base
- # The base URI for the service.
- # @param [String] method_name
- # The identifier for the method.
- # @param [Hash] discovery_document
- # The section of the discovery document that applies to this method.
- #
- # @return [Google::APIClient::Method] The constructed method object.
- def initialize(api, method_base, method_name, discovery_document)
- @api = api
- @method_base = method_base
- @name = method_name
- @discovery_document = discovery_document
- end
-
- # @return [String] unparsed discovery document for the method
- attr_reader :discovery_document
-
- ##
- # Returns the API this method belongs to.
- #
- # @return [Google::APIClient::API] The API this method belongs to.
- attr_reader :api
-
- ##
- # Returns the identifier for the method.
- #
- # @return [String] The method identifier.
- attr_reader :name
-
- ##
- # Returns the base URI for the method.
- #
- # @return [Addressable::URI]
- # The base URI that this method will be joined to.
- attr_reader :method_base
-
- ##
- # Updates the method with the new base.
- #
- # @param [Addressable::URI, #to_str, String] new_method_base
- # The new base URI to use for the method.
- def method_base=(new_method_base)
- @method_base = Addressable::URI.parse(new_method_base)
- @uri_template = nil
- end
-
- ##
- # Returns a human-readable description of the method.
- #
- # @return [Hash] The API description.
- def description
- return @discovery_document['description']
- end
-
- ##
- # Returns the method ID.
- #
- # @return [String] The method identifier.
- def id
- return @discovery_document['id']
- end
-
- ##
- # Returns the HTTP method or 'GET' if none is specified.
- #
- # @return [String] The HTTP method that will be used in the request.
- def http_method
- return @discovery_document['httpMethod'] || 'GET'
- end
-
- ##
- # Returns the URI template for the method. A parameter list can be
- # used to expand this into a URI.
- #
- # @return [Addressable::Template] The URI template.
- def uri_template
- return @uri_template ||= Addressable::Template.new(
- self.method_base.join(Addressable::URI.parse("./" + @discovery_document['path']))
- )
- end
-
- ##
- # Returns media upload information for this method, if supported
- #
- # @return [Google::APIClient::MediaUpload] Description of upload endpoints
- def media_upload
- if @discovery_document['mediaUpload']
- return @media_upload ||= Google::APIClient::MediaUpload.new(self, self.method_base, @discovery_document['mediaUpload'])
- else
- return nil
- end
- end
-
- ##
- # Returns the Schema object for the method's request, if any.
- #
- # @return [Google::APIClient::Schema] The request schema.
- def request_schema
- if @discovery_document['request']
- schema_name = @discovery_document['request']['$ref']
- return @api.schemas[schema_name]
- else
- return nil
- end
- end
-
- ##
- # Returns the Schema object for the method's response, if any.
- #
- # @return [Google::APIClient::Schema] The response schema.
- def response_schema
- if @discovery_document['response']
- schema_name = @discovery_document['response']['$ref']
- return @api.schemas[schema_name]
- else
- return nil
- end
- end
-
- ##
- # Normalizes parameters, converting to the appropriate types.
- #
- # @param [Hash, Array] parameters
- # The parameters to normalize.
- #
- # @return [Hash] The normalized parameters.
- def normalize_parameters(parameters={})
- # Convert keys to Strings when appropriate
- if parameters.kind_of?(Hash) || parameters.kind_of?(Array)
- # Returning an array since parameters can be repeated (ie, Adsense Management API)
- parameters = parameters.inject([]) do |accu, (k, v)|
- k = k.to_s if k.kind_of?(Symbol)
- k = k.to_str if k.respond_to?(:to_str)
- unless k.kind_of?(String)
- raise TypeError, "Expected String, got #{k.class}."
- end
- accu << [k, v]
- accu
- end
- else
- raise TypeError,
- "Expected Hash or Array, got #{parameters.class}."
- end
- return parameters
- end
-
- ##
- # Expands the method's URI template using a parameter list.
- #
- # @api private
- # @param [Hash, Array] parameters
- # The parameter list to use.
- #
- # @return [Addressable::URI] The URI after expansion.
- def generate_uri(parameters={})
- parameters = self.normalize_parameters(parameters)
-
- self.validate_parameters(parameters)
- template_variables = self.uri_template.variables
- upload_type = parameters.assoc('uploadType') || parameters.assoc('upload_type')
- if upload_type
- unless self.media_upload
- raise ArgumentException, "Media upload not supported for this method"
- end
- case upload_type.last
- when 'media', 'multipart', 'resumable'
- uri = self.media_upload.uri_template.expand(parameters)
- else
- raise ArgumentException, "Invalid uploadType '#{upload_type}'"
- end
- else
- uri = self.uri_template.expand(parameters)
- end
- query_parameters = parameters.reject do |k, v|
- template_variables.include?(k)
- end
- # encode all non-template parameters
- params = ""
- unless query_parameters.empty?
- params = "?" + Addressable::URI.form_encode(query_parameters.sort)
- end
- # Normalization is necessary because of undesirable percent-escaping
- # during URI template expansion
- return uri.normalize + params
- end
-
- ##
- # Generates an HTTP request for this method.
- #
- # @api private
- # @param [Hash, Array] parameters
- # The parameters to send.
- # @param [String, StringIO] body The body for the HTTP request.
- # @param [Hash, Array] headers The HTTP headers for the request.
- # @option options [Faraday::Connection] :connection
- # The HTTP connection to use.
- #
- # @return [Array] The generated HTTP request.
- def generate_request(parameters={}, body='', headers={}, options={})
- if !headers.kind_of?(Array) && !headers.kind_of?(Hash)
- raise TypeError, "Expected Hash or Array, got #{headers.class}."
- end
- method = self.http_method.to_s.downcase.to_sym
- uri = self.generate_uri(parameters)
- headers = Faraday::Utils::Headers.new(headers)
- return [method, uri, headers, body]
- end
-
-
- ##
- # Returns a Hash of the parameter descriptions for
- # this method.
- #
- # @return [Hash] The parameter descriptions.
- def parameter_descriptions
- @parameter_descriptions ||= (
- @discovery_document['parameters'] || {}
- ).inject({}) { |h,(k,v)| h[k]=v; h }
- end
-
- ##
- # Returns an Array of the parameters for this method.
- #
- # @return [Array] The parameters.
- def parameters
- @parameters ||= ((
- @discovery_document['parameters'] || {}
- ).inject({}) { |h,(k,v)| h[k]=v; h }).keys
- end
-
- ##
- # Returns an Array of the required parameters for this
- # method.
- #
- # @return [Array] The required parameters.
- #
- # @example
- # # A list of all required parameters.
- # method.required_parameters
- def required_parameters
- @required_parameters ||= ((self.parameter_descriptions.select do |k, v|
- v['required']
- end).inject({}) { |h,(k,v)| h[k]=v; h }).keys
- end
-
- ##
- # Returns an Array of the optional parameters for this
- # method.
- #
- # @return [Array] The optional parameters.
- #
- # @example
- # # A list of all optional parameters.
- # method.optional_parameters
- def optional_parameters
- @optional_parameters ||= ((self.parameter_descriptions.reject do |k, v|
- v['required']
- end).inject({}) { |h,(k,v)| h[k]=v; h }).keys
- end
-
- ##
- # Verifies that the parameters are valid for this method. Raises an
- # exception if validation fails.
- #
- # @api private
- # @param [Hash, Array] parameters
- # The parameters to verify.
- #
- # @return [NilClass] nil if validation passes.
- def validate_parameters(parameters={})
- parameters = self.normalize_parameters(parameters)
- required_variables = ((self.parameter_descriptions.select do |k, v|
- v['required']
- end).inject({}) { |h,(k,v)| h[k]=v; h }).keys
- missing_variables = required_variables - parameters.map { |(k, _)| k }
- if missing_variables.size > 0
- raise ArgumentError,
- "Missing required parameters: #{missing_variables.join(', ')}."
- end
- parameters.each do |k, v|
- # Handle repeated parameters.
- if self.parameter_descriptions[k] &&
- self.parameter_descriptions[k]['repeated'] &&
- v.kind_of?(Array)
- # If this is a repeated parameter and we've got an array as a
- # value, just provide the whole array to the loop below.
- items = v
- else
- # If this is not a repeated parameter, or if it is but we're
- # being given a single value, wrap the value in an array, so that
- # the loop below still works for the single element.
- items = [v]
- end
-
- items.each do |item|
- if self.parameter_descriptions[k]
- enum = self.parameter_descriptions[k]['enum']
- if enum && !enum.include?(item)
- raise ArgumentError,
- "Parameter '#{k}' has an invalid value: #{item}. " +
- "Must be one of #{enum.inspect}."
- end
- pattern = self.parameter_descriptions[k]['pattern']
- if pattern
- regexp = Regexp.new("^#{pattern}$")
- if item !~ regexp
- raise ArgumentError,
- "Parameter '#{k}' has an invalid value: #{item}. " +
- "Must match: /^#{pattern}$/."
- end
- end
- end
- end
- end
- return nil
- end
-
- ##
- # Returns a String representation of the method's state.
- #
- # @return [String] The method's state, as a String.
- def inspect
- sprintf(
- "#<%s:%#0x ID:%s>",
- self.class.to_s, self.object_id, self.id
- )
- end
- end
- end
-end
diff --git a/lib/google/api_client/discovery/resource.rb b/lib/google/api_client/discovery/resource.rb
deleted file mode 100644
index 9b757c684da..00000000000
--- a/lib/google/api_client/discovery/resource.rb
+++ /dev/null
@@ -1,156 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-require 'addressable/uri'
-
-require 'active_support/inflector'
-require 'google/api_client/discovery/method'
-
-
-module Google
- class APIClient
- ##
- # A resource that has been described by a discovery document.
- class Resource
-
- ##
- # Creates a description of a particular version of a resource.
- #
- # @param [Google::APIClient::API] api
- # The API this resource belongs to.
- # @param [Addressable::URI] method_base
- # The base URI for the service.
- # @param [String] resource_name
- # The identifier for the resource.
- # @param [Hash] discovery_document
- # The section of the discovery document that applies to this resource.
- #
- # @return [Google::APIClient::Resource] The constructed resource object.
- def initialize(api, method_base, resource_name, discovery_document)
- @api = api
- @method_base = method_base
- @name = resource_name
- @discovery_document = discovery_document
- metaclass = (class <String representation of the resource's state.
- #
- # @return [String] The resource's state, as a String.
- def inspect
- sprintf(
- "#<%s:%#0x NAME:%s>", self.class.to_s, self.object_id, self.name
- )
- end
- end
- end
-end
diff --git a/lib/google/api_client/discovery/schema.rb b/lib/google/api_client/discovery/schema.rb
deleted file mode 100644
index 57666e698db..00000000000
--- a/lib/google/api_client/discovery/schema.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-require 'time'
-require 'multi_json'
-require 'compat/multi_json'
-require 'base64'
-require 'autoparse'
-require 'addressable/uri'
-require 'addressable/template'
-
-require 'active_support/inflector'
-require 'google/api_client/errors'
-
-
-module Google
- class APIClient
- ##
- # @api private
- module Schema
- def self.parse(api, schema_data)
- # This method is super-long, but hard to break up due to the
- # unavoidable dependence on closures and execution context.
- schema_name = schema_data['id']
-
- # Due to an oversight, schema IDs may not be URI references.
- # TODO(bobaman): Remove this code once this has been resolved.
- schema_uri = (
- api.document_base +
- (schema_name[0..0] != '#' ? '#' + schema_name : schema_name)
- )
-
- # Due to an oversight, schema IDs may not be URI references.
- # TODO(bobaman): Remove this whole lambda once this has been resolved.
- reformat_references = lambda do |data|
- # This code is not particularly efficient due to recursive traversal
- # and excess object creation, but this hopefully shouldn't be an
- # issue since it should only be called only once per schema per
- # process.
- if data.kind_of?(Hash) &&
- data['$ref'] && !data['$ref'].kind_of?(Hash)
- if data['$ref'].respond_to?(:to_str)
- reference = data['$ref'].to_str
- else
- raise TypeError, "Expected String, got #{data['$ref'].class}"
- end
- reference = '#' + reference if reference[0..0] != '#'
- data.merge({
- '$ref' => reference
- })
- elsif data.kind_of?(Hash)
- data.inject({}) do |accu, (key, value)|
- if value.kind_of?(Hash)
- accu[key] = reformat_references.call(value)
- else
- accu[key] = value
- end
- accu
- end
- else
- data
- end
- end
- schema_data = reformat_references.call(schema_data)
-
- if schema_name
- api_name_string = ActiveSupport::Inflector.camelize(api.name)
- api_version_string = ActiveSupport::Inflector.camelize(api.version).gsub('.', '_')
- # This is for compatibility with Ruby 1.8.7.
- # TODO(bobaman) Remove this when we eventually stop supporting 1.8.7.
- args = []
- args << false if Class.method(:const_defined?).arity != 1
- if Google::APIClient::Schema.const_defined?(api_name_string, *args)
- api_name = Google::APIClient::Schema.const_get(
- api_name_string, *args
- )
- else
- api_name = Google::APIClient::Schema.const_set(
- api_name_string, Module.new
- )
- end
- if api_name.const_defined?(api_version_string, *args)
- api_version = api_name.const_get(api_version_string, *args)
- else
- api_version = api_name.const_set(api_version_string, Module.new)
- end
- if api_version.const_defined?(schema_name, *args)
- schema_class = api_version.const_get(schema_name, *args)
- end
- end
-
- # It's possible the schema has already been defined. If so, don't
- # redefine it. This means that reloading a schema which has already
- # been loaded into memory is not possible.
- unless schema_class
- schema_class = AutoParse.generate(schema_data, :uri => schema_uri)
- if schema_name
- api_version.const_set(schema_name, schema_class)
- end
- end
- return schema_class
- end
- end
- end
-end
diff --git a/lib/google/api_client/environment.rb b/lib/google/api_client/environment.rb
deleted file mode 100644
index 00cc864a1c7..00000000000
--- a/lib/google/api_client/environment.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-module Google
- class APIClient
- module ENV
- OS_VERSION = begin
- if RUBY_PLATFORM =~ /mswin|win32|mingw|bccwin|cygwin/
- # TODO(bobaman)
- # Confirm that all of these Windows environments actually have access
- # to the `ver` command.
- `ver`.sub(/\s*\[Version\s*/, '/').sub(']', '')
- elsif RUBY_PLATFORM =~ /darwin/i
- "Mac OS X/#{`sw_vers -productVersion`}"
- elsif RUBY_PLATFORM == 'java'
- # Get the information from java system properties to avoid spawning a
- # sub-process, which is not friendly in some contexts (web servers).
- require 'java'
- name = java.lang.System.getProperty('os.name')
- version = java.lang.System.getProperty('os.version')
- "#{name}/#{version}"
- else
- `uname -sr`.sub(' ', '/')
- end
- rescue Exception
- RUBY_PLATFORM
- end.strip
- end
- end
-end
diff --git a/lib/google/api_client/errors.rb b/lib/google/api_client/errors.rb
deleted file mode 100644
index 9644c692a21..00000000000
--- a/lib/google/api_client/errors.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-module Google
- class APIClient
- ##
- # An error which is raised when there is an unexpected response or other
- # transport error that prevents an operation from succeeding.
- class TransmissionError < StandardError
- attr_reader :result
- def initialize(message = nil, result = nil)
- super(message)
- @result = result
- end
- end
-
- ##
- # An exception that is raised if a redirect is required
- #
- class RedirectError < TransmissionError
- end
-
- ##
- # An exception that is raised if a method is called with missing or
- # invalid parameter values.
- class ValidationError < StandardError
- end
-
- ##
- # A 4xx class HTTP error occurred.
- class ClientError < TransmissionError
- end
-
- ##
- # A 401 HTTP error occurred.
- class AuthorizationError < ClientError
- end
-
- ##
- # A 5xx class HTTP error occurred.
- class ServerError < TransmissionError
- end
-
- ##
- # An exception that is raised if an ID token could not be validated.
- class InvalidIDTokenError < StandardError
- end
-
- # Error class for problems in batch requests.
- class BatchError < StandardError
- end
- end
-end
diff --git a/lib/google/api_client/gzip.rb b/lib/google/api_client/gzip.rb
deleted file mode 100644
index 42fabbbdba4..00000000000
--- a/lib/google/api_client/gzip.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require 'faraday'
-require 'zlib'
-
-module Google
- class APIClient
- class Gzip < Faraday::Response::Middleware
- include Google::APIClient::Logging
-
- def on_complete(env)
- encoding = env[:response_headers]['content-encoding'].to_s.downcase
- case encoding
- when 'gzip'
- logger.debug { "Decompressing gzip encoded response (#{env[:body].length} bytes)" }
- env[:body] = Zlib::GzipReader.new(StringIO.new(env[:body])).read
- env[:response_headers].delete('content-encoding')
- logger.debug { "Decompressed (#{env[:body].length} bytes)" }
- when 'deflate'
- logger.debug{ "Decompressing deflate encoded response (#{env[:body].length} bytes)" }
- env[:body] = Zlib::Inflate.inflate(env[:body])
- env[:response_headers].delete('content-encoding')
- logger.debug { "Decompressed (#{env[:body].length} bytes)" }
- end
- end
- end
- end
-end
-
-Faraday::Response.register_middleware :gzip => Google::APIClient::Gzip
\ No newline at end of file
diff --git a/lib/google/api_client/logging.rb b/lib/google/api_client/logging.rb
deleted file mode 100644
index 09a075b5c9a..00000000000
--- a/lib/google/api_client/logging.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require 'logger'
-
-module Google
- class APIClient
-
- class << self
- ##
- # Logger for the API client
- #
- # @return [Logger] logger instance.
- attr_accessor :logger
- end
-
- self.logger = Logger.new(STDOUT)
- self.logger.level = Logger::WARN
-
- ##
- # Module to make accessing the logger simpler
- module Logging
- ##
- # Logger for the API client
- #
- # @return [Logger] logger instance.
- def logger
- Google::APIClient.logger
- end
- end
-
- end
-
-
-end
\ No newline at end of file
diff --git a/lib/google/api_client/media.rb b/lib/google/api_client/media.rb
deleted file mode 100644
index 5066bcebdfa..00000000000
--- a/lib/google/api_client/media.rb
+++ /dev/null
@@ -1,259 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-require 'google/api_client/reference'
-
-module Google
- class APIClient
- ##
- # Uploadable media support. Holds an IO stream & content type.
- #
- # @see Faraday::UploadIO
- # @example
- # media = Google::APIClient::UploadIO.new('mymovie.m4v', 'video/mp4')
- class UploadIO < Faraday::UploadIO
-
- # @return [Fixnum] Size of chunks to upload. Default is nil, meaning upload the entire file in a single request
- attr_accessor :chunk_size
-
- ##
- # Get the length of the stream
- #
- # @return [Fixnum]
- # Length of stream, in bytes
- def length
- io.respond_to?(:length) ? io.length : File.size(local_path)
- end
- end
-
- ##
- # Wraps an input stream and limits data to a given range
- #
- # @example
- # chunk = Google::APIClient::RangedIO.new(io, 0, 1000)
- class RangedIO
- ##
- # Bind an input stream to a specific range.
- #
- # @param [IO] io
- # Source input stream
- # @param [Fixnum] offset
- # Starting offset of the range
- # @param [Fixnum] length
- # Length of range
- def initialize(io, offset, length)
- @io = io
- @offset = offset
- @length = length
- self.rewind
- end
-
- ##
- # @see IO#read
- def read(amount = nil, buf = nil)
- buffer = buf || ''
- if amount.nil?
- size = @length - @pos
- done = ''
- elsif amount == 0
- size = 0
- done = ''
- else
- size = [@length - @pos, amount].min
- done = nil
- end
-
- if size > 0
- result = @io.read(size)
- result.force_encoding("BINARY") if result.respond_to?(:force_encoding)
- buffer << result if result
- @pos = @pos + size
- end
-
- if buffer.length > 0
- buffer
- else
- done
- end
- end
-
- ##
- # @see IO#rewind
- def rewind
- self.pos = 0
- end
-
- ##
- # @see IO#pos
- def pos
- @pos
- end
-
- ##
- # @see IO#pos=
- def pos=(pos)
- @pos = pos
- @io.pos = @offset + pos
- end
- end
-
- ##
- # Resumable uploader.
- #
- class ResumableUpload < Request
- # @return [Fixnum] Max bytes to send in a single request
- attr_accessor :chunk_size
-
- ##
- # Creates a new uploader.
- #
- # @param [Hash] options
- # Request options
- def initialize(options={})
- super options
- self.uri = options[:uri]
- self.http_method = :put
- @offset = options[:offset] || 0
- @complete = false
- @expired = false
- end
-
- ##
- # Sends all remaining chunks to the server
- #
- # @deprecated Pass the instance to {Google::APIClient#execute} instead
- #
- # @param [Google::APIClient] api_client
- # API Client instance to use for sending
- def send_all(api_client)
- result = nil
- until complete?
- result = send_chunk(api_client)
- break unless result.status == 308
- end
- return result
- end
-
-
- ##
- # Sends the next chunk to the server
- #
- # @deprecated Pass the instance to {Google::APIClient#execute} instead
- #
- # @param [Google::APIClient] api_client
- # API Client instance to use for sending
- def send_chunk(api_client)
- return api_client.execute(self)
- end
-
- ##
- # Check if upload is complete
- #
- # @return [TrueClass, FalseClass]
- # Whether or not the upload complete successfully
- def complete?
- return @complete
- end
-
- ##
- # Check if the upload URL expired (upload not completed in alotted time.)
- # Expired uploads must be restarted from the beginning
- #
- # @return [TrueClass, FalseClass]
- # Whether or not the upload has expired and can not be resumed
- def expired?
- return @expired
- end
-
- ##
- # Check if upload is resumable. That is, neither complete nor expired
- #
- # @return [TrueClass, FalseClass] True if upload can be resumed
- def resumable?
- return !(self.complete? or self.expired?)
- end
-
- ##
- # Convert to an HTTP request. Returns components in order of method, URI,
- # request headers, and body
- #
- # @api private
- #
- # @return [Array<(Symbol, Addressable::URI, Hash, [#read,#to_str])>]
- def to_http_request
- if @complete
- raise Google::APIClient::ClientError, "Upload already complete"
- elsif @offset.nil?
- self.headers.update({
- 'Content-Length' => "0",
- 'Content-Range' => "bytes */#{media.length}" })
- else
- start_offset = @offset
- remaining = self.media.length - start_offset
- chunk_size = self.media.chunk_size || self.chunk_size || self.media.length
- content_length = [remaining, chunk_size].min
- chunk = RangedIO.new(self.media.io, start_offset, content_length)
- end_offset = start_offset + content_length - 1
- self.headers.update({
- 'Content-Length' => "#{content_length}",
- 'Content-Type' => self.media.content_type,
- 'Content-Range' => "bytes #{start_offset}-#{end_offset}/#{media.length}" })
- self.body = chunk
- end
- super
- end
-
- ##
- # Check the result from the server, updating the offset and/or location
- # if available.
- #
- # @api private
- #
- # @param [Faraday::Response] response
- # HTTP response
- #
- # @return [Google::APIClient::Result]
- # Processed API response
- def process_http_response(response)
- case response.status
- when 200...299
- @complete = true
- when 308
- range = response.headers['range']
- if range
- @offset = range.scan(/\d+/).collect{|x| Integer(x)}.last + 1
- end
- if response.headers['location']
- self.uri = response.headers['location']
- end
- when 400...499
- @expired = true
- when 500...599
- # Invalidate the offset to mark it needs to be queried on the
- # next request
- @offset = nil
- end
- return Google::APIClient::Result.new(self, response)
- end
-
- ##
- # Hashified verison of the API request
- #
- # @return [Hash]
- def to_hash
- super.merge(:offset => @offset)
- end
-
- end
- end
-end
\ No newline at end of file
diff --git a/lib/google/api_client/railtie.rb b/lib/google/api_client/railtie.rb
deleted file mode 100644
index 86d9a6b204b..00000000000
--- a/lib/google/api_client/railtie.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'rails/railtie'
-require 'google/api_client/logging'
-
-module Google
- class APIClient
-
- ##
- # Optional support class for Rails. Currently replaces the built-in logger
- # with Rails' application log.
- #
- class Railtie < Rails::Railtie
- initializer 'google-api-client' do |app|
- logger = app.config.logger || Rails.logger
- Google::APIClient.logger = logger unless logger.nil?
- end
- end
- end
-end
diff --git a/lib/google/api_client/request.rb b/lib/google/api_client/request.rb
deleted file mode 100644
index d043e001628..00000000000
--- a/lib/google/api_client/request.rb
+++ /dev/null
@@ -1,350 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'faraday'
-require 'faraday/request/multipart'
-require 'compat/multi_json'
-require 'addressable/uri'
-require 'stringio'
-require 'google/api_client/discovery'
-require 'google/api_client/logging'
-
-module Google
- class APIClient
-
- ##
- # Represents an API request.
- class Request
- include Google::APIClient::Logging
-
- MULTIPART_BOUNDARY = "-----------RubyApiMultipartPost".freeze
-
- # @return [Hash] Request parameters
- attr_reader :parameters
- # @return [Hash] Additional HTTP headers
- attr_reader :headers
- # @return [Google::APIClient::Method] API method to invoke
- attr_reader :api_method
- # @return [Google::APIClient::UploadIO] File to upload
- attr_accessor :media
- # @return [#generated_authenticated_request] User credentials
- attr_accessor :authorization
- # @return [TrueClass,FalseClass] True if request should include credentials
- attr_accessor :authenticated
- # @return [#read, #to_str] Request body
- attr_accessor :body
-
- ##
- # Build a request
- #
- # @param [Hash] options
- # @option options [Hash, Array] :parameters
- # Request parameters for the API method.
- # @option options [Google::APIClient::Method] :api_method
- # API method to invoke. Either :api_method or :uri must be specified
- # @option options [TrueClass, FalseClass] :authenticated
- # True if request should include credentials. Implicitly true if
- # unspecified and :authorization present
- # @option options [#generate_signed_request] :authorization
- # OAuth credentials
- # @option options [Google::APIClient::UploadIO] :media
- # File to upload, if media upload request
- # @option options [#to_json, #to_hash] :body_object
- # Main body of the API request. Typically hash or object that can
- # be serialized to JSON
- # @option options [#read, #to_str] :body
- # Raw body to send in POST/PUT requests
- # @option options [String, Addressable::URI] :uri
- # URI to request. Either :api_method or :uri must be specified
- # @option options [String, Symbol] :http_method
- # HTTP method when requesting a URI
- def initialize(options={})
- @parameters = Faraday::Utils::ParamsHash.new
- @headers = Faraday::Utils::Headers.new
-
- self.parameters.merge!(options[:parameters]) unless options[:parameters].nil?
- self.headers.merge!(options[:headers]) unless options[:headers].nil?
- self.api_method = options[:api_method]
- self.authenticated = options[:authenticated]
- self.authorization = options[:authorization]
-
- # These parameters are handled differently because they're not
- # parameters to the API method, but rather to the API system.
- self.parameters['key'] ||= options[:key] if options[:key]
- self.parameters['userIp'] ||= options[:user_ip] if options[:user_ip]
-
- if options[:media]
- self.initialize_media_upload(options)
- elsif options[:body]
- self.body = options[:body]
- elsif options[:body_object]
- self.headers['Content-Type'] ||= 'application/json'
- self.body = serialize_body(options[:body_object])
- else
- self.body = ''
- end
-
- unless self.api_method
- self.http_method = options[:http_method] || 'GET'
- self.uri = options[:uri]
- end
- end
-
- # @!attribute [r] upload_type
- # @return [String] protocol used for upload
- def upload_type
- return self.parameters['uploadType'] || self.parameters['upload_type']
- end
-
- # @!attribute http_method
- # @return [Symbol] HTTP method if invoking a URI
- def http_method
- return @http_method ||= self.api_method.http_method.to_s.downcase.to_sym
- end
-
- def http_method=(new_http_method)
- if new_http_method.kind_of?(Symbol)
- @http_method = new_http_method.to_s.downcase.to_sym
- elsif new_http_method.respond_to?(:to_str)
- @http_method = new_http_method.to_s.downcase.to_sym
- else
- raise TypeError,
- "Expected String or Symbol, got #{new_http_method.class}."
- end
- end
-
- def api_method=(new_api_method)
- if new_api_method.nil? || new_api_method.kind_of?(Google::APIClient::Method)
- @api_method = new_api_method
- else
- raise TypeError,
- "Expected Google::APIClient::Method, got #{new_api_method.class}."
- end
- end
-
- # @!attribute uri
- # @return [Addressable::URI] URI to send request
- def uri
- return @uri ||= self.api_method.generate_uri(self.parameters)
- end
-
- def uri=(new_uri)
- @uri = Addressable::URI.parse(new_uri)
- @parameters.update(@uri.query_values) unless @uri.query_values.nil?
- end
-
-
- # Transmits the request with the given connection
- #
- # @api private
- #
- # @param [Faraday::Connection] connection
- # the connection to transmit with
- # @param [TrueValue,FalseValue] is_retry
- # True if request has been previous sent
- #
- # @return [Google::APIClient::Result]
- # result of API request
- def send(connection, is_retry = false)
- self.body.rewind if is_retry && self.body.respond_to?(:rewind)
- env = self.to_env(connection)
- logger.debug { "#{self.class} Sending API request #{env[:method]} #{env[:url].to_s} #{env[:request_headers]}" }
- http_response = connection.app.call(env)
- result = self.process_http_response(http_response)
-
- logger.debug { "#{self.class} Result: #{result.status} #{result.headers}" }
-
- # Resumamble slightly different than other upload protocols in that it requires at least
- # 2 requests.
- if result.status == 200 && self.upload_type == 'resumable' && self.media
- upload = result.resumable_upload
- unless upload.complete?
- logger.debug { "#{self.class} Sending upload body" }
- result = upload.send(connection)
- end
- end
- return result
- end
-
- # Convert to an HTTP request. Returns components in order of method, URI,
- # request headers, and body
- #
- # @api private
- #
- # @return [Array<(Symbol, Addressable::URI, Hash, [#read,#to_str])>]
- def to_http_request
- request = (
- if self.api_method
- self.api_method.generate_request(self.parameters, self.body, self.headers)
- elsif self.uri
- unless self.parameters.empty?
- self.uri.query = Addressable::URI.form_encode(self.parameters)
- end
- [self.http_method, self.uri.to_s, self.headers, self.body]
- end)
- return request
- end
-
- ##
- # Hashified verison of the API request
- #
- # @return [Hash]
- def to_hash
- options = {}
- if self.api_method
- options[:api_method] = self.api_method
- options[:parameters] = self.parameters
- else
- options[:http_method] = self.http_method
- options[:uri] = self.uri
- end
- options[:headers] = self.headers
- options[:body] = self.body
- options[:media] = self.media
- unless self.authorization.nil?
- options[:authorization] = self.authorization
- end
- return options
- end
-
- ##
- # Prepares the request for execution, building a hash of parts
- # suitable for sending to Faraday::Connection.
- #
- # @api private
- #
- # @param [Faraday::Connection] connection
- # Connection for building the request
- #
- # @return [Hash]
- # Encoded request
- def to_env(connection)
- method, uri, headers, body = self.to_http_request
- http_request = connection.build_request(method) do |req|
- req.url(uri.to_s)
- req.headers.update(headers)
- req.body = body
- end
-
- if self.authorization.respond_to?(:generate_authenticated_request)
- http_request = self.authorization.generate_authenticated_request(
- :request => http_request,
- :connection => connection
- )
- end
-
- http_request.to_env(connection)
- end
-
- ##
- # Convert HTTP response to an API Result
- #
- # @api private
- #
- # @param [Faraday::Response] response
- # HTTP response
- #
- # @return [Google::APIClient::Result]
- # Processed API response
- def process_http_response(response)
- Result.new(self, response)
- end
-
- protected
-
- ##
- # Adjust headers & body for media uploads
- #
- # @api private
- #
- # @param [Hash] options
- # @option options [Hash, Array] :parameters
- # Request parameters for the API method.
- # @option options [Google::APIClient::UploadIO] :media
- # File to upload, if media upload request
- # @option options [#to_json, #to_hash] :body_object
- # Main body of the API request. Typically hash or object that can
- # be serialized to JSON
- # @option options [#read, #to_str] :body
- # Raw body to send in POST/PUT requests
- def initialize_media_upload(options)
- self.media = options[:media]
- case self.upload_type
- when "media"
- if options[:body] || options[:body_object]
- raise ArgumentError, "Can not specify body & body object for simple uploads"
- end
- self.headers['Content-Type'] ||= self.media.content_type
- self.headers['Content-Length'] ||= self.media.length.to_s
- self.body = self.media
- when "multipart"
- unless options[:body_object]
- raise ArgumentError, "Multipart requested but no body object"
- end
- metadata = StringIO.new(serialize_body(options[:body_object]))
- build_multipart([Faraday::UploadIO.new(metadata, 'application/json', 'file.json'), self.media])
- when "resumable"
- file_length = self.media.length
- self.headers['X-Upload-Content-Type'] = self.media.content_type
- self.headers['X-Upload-Content-Length'] = file_length.to_s
- if options[:body_object]
- self.headers['Content-Type'] ||= 'application/json'
- self.body = serialize_body(options[:body_object])
- else
- self.body = ''
- end
- end
- end
-
- ##
- # Assemble a multipart message from a set of parts
- #
- # @api private
- #
- # @param [Array<[#read,#to_str]>] parts
- # Array of parts to encode.
- # @param [String] mime_type
- # MIME type of the message
- # @param [String] boundary
- # Boundary for separating each part of the message
- def build_multipart(parts, mime_type = 'multipart/related', boundary = MULTIPART_BOUNDARY)
- env = Faraday::Env.new
- env.request = Faraday::RequestOptions.new
- env.request.boundary = boundary
- env.request_headers = {'Content-Type' => "#{mime_type};boundary=#{boundary}"}
- multipart = Faraday::Request::Multipart.new
- self.body = multipart.create_multipart(env, parts.map {|part| [nil, part]})
- self.headers.update(env[:request_headers])
- end
-
- ##
- # Serialize body object to JSON
- #
- # @api private
- #
- # @param [#to_json,#to_hash] body
- # object to serialize
- #
- # @return [String]
- # JSON
- def serialize_body(body)
- return body.to_json if body.respond_to?(:to_json)
- return MultiJson.dump(body.to_hash) if body.respond_to?(:to_hash)
- raise TypeError, 'Could not convert body object to JSON.' +
- 'Must respond to :to_json or :to_hash.'
- end
-
- end
- end
-end
diff --git a/lib/google/api_client/result.rb b/lib/google/api_client/result.rb
deleted file mode 100644
index c48bec04a5d..00000000000
--- a/lib/google/api_client/result.rb
+++ /dev/null
@@ -1,255 +0,0 @@
-# Copyright 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-module Google
- class APIClient
- ##
- # This class wraps a result returned by an API call.
- class Result
- extend Forwardable
-
- ##
- # Init the result
- #
- # @param [Google::APIClient::Request] request
- # The original request
- # @param [Faraday::Response] response
- # Raw HTTP Response
- def initialize(request, response)
- @request = request
- @response = response
- @media_upload = reference if reference.kind_of?(ResumableUpload)
- end
-
- # @return [Google::APIClient::Request] Original request object
- attr_reader :request
- # @return [Faraday::Response] HTTP response
- attr_reader :response
- # @!attribute [r] reference
- # @return [Google::APIClient::Request] Original request object
- # @deprecated See {#request}
- alias_method :reference, :request # For compatibility with pre-beta clients
-
- # @!attribute [r] status
- # @return [Fixnum] HTTP status code
- # @!attribute [r] headers
- # @return [Hash] HTTP response headers
- # @!attribute [r] body
- # @return [String] HTTP response body
- def_delegators :@response, :status, :headers, :body
-
- # @!attribute [r] resumable_upload
- # @return [Google::APIClient::ResumableUpload] For resuming media uploads
- def resumable_upload
- @media_upload ||= (
- options = self.reference.to_hash.merge(
- :uri => self.headers['location'],
- :media => self.reference.media
- )
- Google::APIClient::ResumableUpload.new(options)
- )
- end
-
- ##
- # Get the content type of the response
- # @!attribute [r] media_type
- # @return [String]
- # Value of content-type header
- def media_type
- _, content_type = self.headers.detect do |h, v|
- h.downcase == 'Content-Type'.downcase
- end
- if content_type
- return content_type[/^([^;]*);?.*$/, 1].strip.downcase
- else
- return nil
- end
- end
-
- ##
- # Check if request failed
- #
- # @!attribute [r] error?
- # @return [TrueClass, FalseClass]
- # true if result of operation is an error
- def error?
- return self.response.status >= 400
- end
-
- ##
- # Check if request was successful
- #
- # @!attribute [r] success?
- # @return [TrueClass, FalseClass]
- # true if result of operation was successful
- def success?
- return !self.error?
- end
-
- ##
- # Extracts error messages from the response body
- #
- # @!attribute [r] error_message
- # @return [String]
- # error message, if available
- def error_message
- if self.data?
- if self.data.respond_to?(:error) &&
- self.data.error.respond_to?(:message)
- # You're going to get a terrible error message if the response isn't
- # parsed successfully as an error.
- return self.data.error.message
- elsif self.data['error'] && self.data['error']['message']
- return self.data['error']['message']
- end
- end
- return self.body
- end
-
- ##
- # Check for parsable data in response
- #
- # @!attribute [r] data?
- # @return [TrueClass, FalseClass]
- # true if body can be parsed
- def data?
- !(self.body.nil? || self.body.empty? || self.media_type != 'application/json')
- end
-
- ##
- # Return parsed version of the response body.
- #
- # @!attribute [r] data
- # @return [Object, Hash, String]
- # Object if body parsable from API schema, Hash if JSON, raw body if unable to parse
- def data
- return @data ||= (begin
- if self.data?
- media_type = self.media_type
- data = self.body
- case media_type
- when 'application/json'
- data = MultiJson.load(data)
- # Strip data wrapper, if present
- data = data['data'] if data.has_key?('data')
- else
- raise ArgumentError,
- "Content-Type not supported for parsing: #{media_type}"
- end
- if @request.api_method && @request.api_method.response_schema
- # Automatically parse using the schema designated for the
- # response of this API method.
- data = @request.api_method.response_schema.new(data)
- data
- else
- # Otherwise, return the raw unparsed value.
- # This value must be indexable like a Hash.
- data
- end
- end
- end)
- end
-
- ##
- # Get the token used for requesting the next page of data
- #
- # @!attribute [r] next_page_token
- # @return [String]
- # next page token
- def next_page_token
- if self.data.respond_to?(:next_page_token)
- return self.data.next_page_token
- elsif self.data.respond_to?(:[])
- return self.data["nextPageToken"]
- else
- raise TypeError, "Data object did not respond to #next_page_token."
- end
- end
-
- ##
- # Build a request for fetching the next page of data
- #
- # @return [Google::APIClient::Request]
- # API request for retrieving next page, nil if no page token available
- def next_page
- return nil unless self.next_page_token
- merged_parameters = Hash[self.reference.parameters].merge({
- self.page_token_param => self.next_page_token
- })
- # Because Requests can be coerced to Hashes, we can merge them,
- # preserving all context except the API method parameters that we're
- # using for pagination.
- return Google::APIClient::Request.new(
- Hash[self.reference].merge(:parameters => merged_parameters)
- )
- end
-
- ##
- # Get the token used for requesting the previous page of data
- #
- # @!attribute [r] prev_page_token
- # @return [String]
- # previous page token
- def prev_page_token
- if self.data.respond_to?(:prev_page_token)
- return self.data.prev_page_token
- elsif self.data.respond_to?(:[])
- return self.data["prevPageToken"]
- else
- raise TypeError, "Data object did not respond to #next_page_token."
- end
- end
-
- ##
- # Build a request for fetching the previous page of data
- #
- # @return [Google::APIClient::Request]
- # API request for retrieving previous page, nil if no page token available
- def prev_page
- return nil unless self.prev_page_token
- merged_parameters = Hash[self.reference.parameters].merge({
- self.page_token_param => self.prev_page_token
- })
- # Because Requests can be coerced to Hashes, we can merge them,
- # preserving all context except the API method parameters that we're
- # using for pagination.
- return Google::APIClient::Request.new(
- Hash[self.reference].merge(:parameters => merged_parameters)
- )
- end
-
- ##
- # Pagination scheme used by this request/response
- #
- # @!attribute [r] pagination_type
- # @return [Symbol]
- # currently always :token
- def pagination_type
- return :token
- end
-
- ##
- # Name of the field that contains the pagination token
- #
- # @!attribute [r] page_token_param
- # @return [String]
- # currently always 'pageToken'
- def page_token_param
- return "pageToken"
- end
-
- end
- end
-end
diff --git a/lib/google/api_client/service.rb b/lib/google/api_client/service.rb
deleted file mode 100755
index 28f2605d92a..00000000000
--- a/lib/google/api_client/service.rb
+++ /dev/null
@@ -1,233 +0,0 @@
-# Copyright 2013 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'google/api_client'
-require 'google/api_client/service/stub_generator'
-require 'google/api_client/service/resource'
-require 'google/api_client/service/request'
-require 'google/api_client/service/result'
-require 'google/api_client/service/batch'
-require 'google/api_client/service/simple_file_store'
-
-module Google
- class APIClient
-
- ##
- # Experimental new programming interface at the API level.
- # Hides Google::APIClient. Designed to be easier to use, with less code.
- #
- # @example
- # calendar = Google::APIClient::Service.new('calendar', 'v3')
- # result = calendar.events.list('calendarId' => 'primary').execute()
- class Service
- include Google::APIClient::Service::StubGenerator
- extend Forwardable
-
- DEFAULT_CACHE_FILE = 'discovery.cache'
-
- # Cache for discovered APIs.
- @@discovered = {}
-
- ##
- # Creates a new Service.
- #
- # @param [String, Symbol] api_name
- # The name of the API this service will access.
- # @param [String, Symbol] api_version
- # The version of the API this service will access.
- # @param [Hash] options
- # The configuration parameters for the service.
- # @option options [Symbol, #generate_authenticated_request] :authorization
- # (:oauth_1)
- # The authorization mechanism used by the client. The following
- # mechanisms are supported out-of-the-box:
- #
- # :two_legged_oauth_1
- # :oauth_1
- # :oauth_2
- #
- # @option options [Boolean] :auto_refresh_token (true)
- # The setting that controls whether or not the api client attempts to
- # refresh authorization when a 401 is hit in #execute. If the token does
- # not support it, this option is ignored.
- # @option options [String] :application_name
- # The name of the application using the client.
- # @option options [String] :application_version
- # The version number of the application using the client.
- # @option options [String] :host ("www.googleapis.com")
- # The API hostname used by the client. This rarely needs to be changed.
- # @option options [String] :port (443)
- # The port number used by the client. This rarely needs to be changed.
- # @option options [String] :discovery_path ("/discovery/v1")
- # The discovery base path. This rarely needs to be changed.
- # @option options [String] :ca_file
- # Optional set of root certificates to use when validating SSL connections.
- # By default, a bundled set of trusted roots will be used.
- # @option options [#generate_authenticated_request] :authorization
- # The authorization mechanism for requests. Used only if
- # `:authenticated` is `true`.
- # @option options [TrueClass, FalseClass] :authenticated (default: true)
- # `true` if requests must be signed or somehow
- # authenticated, `false` otherwise.
- # @option options [TrueClass, FalseClass] :gzip (default: true)
- # `true` if gzip enabled, `false` otherwise.
- # @option options [Faraday::Connection] :connection
- # A custom connection to be used for all requests.
- # @option options [ActiveSupport::Cache::Store, :default] :discovery_cache
- # A cache store to place the discovery documents for loaded APIs.
- # Avoids unnecessary roundtrips to the discovery service.
- # :default loads the default local file cache store.
- def initialize(api_name, api_version, options = {})
- @api_name = api_name.to_s
- if api_version.nil?
- raise ArgumentError,
- "API version must be set"
- end
- @api_version = api_version.to_s
- if options && !options.respond_to?(:to_hash)
- raise ArgumentError,
- "expected options Hash, got #{options.class}"
- end
-
- params = {}
- [:application_name, :application_version, :authorization, :host, :port,
- :discovery_path, :auto_refresh_token, :key, :user_ip,
- :ca_file].each do |option|
- if options.include? option
- params[option] = options[option]
- end
- end
-
- @client = Google::APIClient.new(params)
-
- @connection = options[:connection] || @client.connection
-
- @options = options
-
- # Initialize cache store. Default to SimpleFileStore if :cache_store
- # is not provided and we have write permissions.
- if options.include? :cache_store
- @cache_store = options[:cache_store]
- else
- cache_exists = File.exists?(DEFAULT_CACHE_FILE)
- if (cache_exists && File.writable?(DEFAULT_CACHE_FILE)) ||
- (!cache_exists && File.writable?(Dir.pwd))
- @cache_store = Google::APIClient::Service::SimpleFileStore.new(
- DEFAULT_CACHE_FILE)
- end
- end
-
- # Attempt to read API definition from memory cache.
- # Not thread-safe, but the worst that can happen is a cache miss.
- unless @api = @@discovered[[api_name, api_version]]
- # Attempt to read API definition from cache store, if there is one.
- # If there's a miss or no cache store, call discovery service.
- if !@cache_store.nil?
- @api = @cache_store.fetch("%s/%s" % [api_name, api_version]) do
- @client.discovered_api(api_name, api_version)
- end
- else
- @api = @client.discovered_api(api_name, api_version)
- end
- @@discovered[[api_name, api_version]] = @api
- end
-
- generate_call_stubs(self, @api)
- end
-
- ##
- # Returns the authorization mechanism used by the service.
- #
- # @return [#generate_authenticated_request] The authorization mechanism.
- def_delegators :@client, :authorization, :authorization=
-
- ##
- # The setting that controls whether or not the service attempts to
- # refresh authorization when a 401 is hit during an API call.
- #
- # @return [Boolean]
- def_delegators :@client, :auto_refresh_token, :auto_refresh_token=
-
- ##
- # The application's API key issued by the API console.
- #
- # @return [String] The API key.
- def_delegators :@client, :key, :key=
-
- ##
- # The Faraday/HTTP connection used by this service.
- #
- # @return [Faraday::Connection]
- attr_accessor :connection
-
- ##
- # The cache store used for storing discovery documents.
- #
- # @return [ActiveSupport::Cache::Store,
- # Google::APIClient::Service::SimpleFileStore,
- # nil]
- attr_reader :cache_store
-
- ##
- # Prepares a Google::APIClient::BatchRequest object to make batched calls.
- # @param [Array] calls
- # Optional array of Google::APIClient::Service::Request to initialize
- # the batch request with.
- # @param [Proc] block
- # Callback for every call's response. Won't be called if a call defined
- # a callback of its own.
- #
- # @yield [Google::APIClient::Service::Result]
- # block to be called when result ready
- def batch(calls = nil, &block)
- Google::APIClient::Service::BatchRequest.new(self, calls, &block)
- end
-
- ##
- # Executes an API request.
- # Do not call directly; this method is only used by Request objects when
- # executing.
- #
- # @param [Google::APIClient::Service::Request,
- # Google::APIClient::Service::BatchCall] request
- # The request to be executed.
- def execute(request)
- if request.instance_of? Google::APIClient::Service::Request
- params = {:api_method => request.method,
- :parameters => request.parameters,
- :connection => @connection}
- if request.respond_to? :body
- if request.body.respond_to? :to_hash
- params[:body_object] = request.body
- else
- params[:body] = request.body
- end
- end
- if request.respond_to? :media
- params[:media] = request.media
- end
- [:authenticated, :gzip].each do |option|
- if @options.include? option
- params[option] = @options[option]
- end
- end
- result = @client.execute(params)
- return Google::APIClient::Service::Result.new(request, result)
- elsif request.instance_of? Google::APIClient::Service::BatchRequest
- @client.execute(request.base_batch, {:connection => @connection})
- end
- end
- end
- end
-end
diff --git a/lib/google/api_client/service/batch.rb b/lib/google/api_client/service/batch.rb
deleted file mode 100644
index 7ba406e6121..00000000000
--- a/lib/google/api_client/service/batch.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright 2013 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'google/api_client/service/result'
-require 'google/api_client/batch'
-
-module Google
- class APIClient
- class Service
-
- ##
- # Helper class to contain the result of an individual batched call.
- #
- class BatchedCallResult < Result
- # @return [Fixnum] Index of the call
- def call_index
- return @base_result.response.call_id.to_i - 1
- end
- end
-
- ##
- #
- #
- class BatchRequest
- ##
- # Creates a new batch request.
- # This class shouldn't be instantiated directly, but rather through
- # Service.batch.
- #
- # @param [Array] calls
- # List of Google::APIClient::Service::Request to be made.
- # @param [Proc] block
- # Callback for every call's response. Won't be called if a call
- # defined a callback of its own.
- #
- # @yield [Google::APIClient::Service::Result]
- # block to be called when result ready
- def initialize(service, calls, &block)
- @service = service
- @base_batch = Google::APIClient::BatchRequest.new
- @global_callback = block if block_given?
-
- if calls && calls.length > 0
- calls.each do |call|
- add(call)
- end
- end
- end
-
- ##
- # Add a new call to the batch request.
- #
- # @param [Google::APIClient::Service::Request] call
- # the call to be added.
- # @param [Proc] block
- # callback for this call's response.
- #
- # @return [Google::APIClient::Service::BatchRequest]
- # the BatchRequest, for chaining
- #
- # @yield [Google::APIClient::Service::Result]
- # block to be called when result ready
- def add(call, &block)
- if !block_given? && @global_callback.nil?
- raise BatchError, 'Request needs a block'
- end
- callback = block || @global_callback
- base_call = {
- :api_method => call.method,
- :parameters => call.parameters
- }
- if call.respond_to? :body
- if call.body.respond_to? :to_hash
- base_call[:body_object] = call.body
- else
- base_call[:body] = call.body
- end
- end
- @base_batch.add(base_call) do |base_result|
- result = Google::APIClient::Service::BatchedCallResult.new(
- call, base_result)
- callback.call(result)
- end
- return self
- end
-
- ##
- # Executes the batch request.
- def execute
- @service.execute(self)
- end
-
- attr_reader :base_batch
-
- end
-
- end
- end
-end
diff --git a/lib/google/api_client/service/request.rb b/lib/google/api_client/service/request.rb
deleted file mode 100755
index dcbc7e32130..00000000000
--- a/lib/google/api_client/service/request.rb
+++ /dev/null
@@ -1,144 +0,0 @@
-# Copyright 2013 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-module Google
- class APIClient
- class Service
- ##
- # Handles an API request.
- # This contains a full definition of the request to be made (including
- # method name, parameters, body and media). The remote API call can be
- # invoked with execute().
- class Request
- ##
- # Build a request.
- # This class should not be directly instantiated in user code;
- # instantiation is handled by the stub methods created on Service and
- # Resource objects.
- #
- # @param [Google::APIClient::Service] service
- # The parent Service instance that will execute the request.
- # @param [Google::APIClient::Method] method
- # The Method instance that describes the API method invoked by the
- # request.
- # @param [Hash] parameters
- # A Hash of parameter names and values to be sent in the API call.
- def initialize(service, method, parameters)
- @service = service
- @method = method
- @parameters = parameters
- @body = nil
- @media = nil
-
- metaclass = (class << self; self; end)
-
- # If applicable, add "body", "body=" and resource-named methods for
- # retrieving and setting the HTTP body for this request.
- # Examples of setting the body for files.insert in the Drive API:
- # request.body = object
- # request.execute
- # OR
- # request.file = object
- # request.execute
- # OR
- # request.body(object).execute
- # OR
- # request.file(object).execute
- # Examples of retrieving the body for files.insert in the Drive API:
- # object = request.body
- # OR
- # object = request.file
- if method.request_schema
- body_name = method.request_schema.data['id'].dup
- body_name[0] = body_name[0].chr.downcase
- body_name_equals = (body_name + '=').to_sym
- body_name = body_name.to_sym
-
- metaclass.send(:define_method, :body) do |*args|
- if args.length == 1
- @body = args.first
- return self
- elsif args.length == 0
- return @body
- else
- raise ArgumentError,
- "wrong number of arguments (#{args.length}; expecting 0 or 1)"
- end
- end
-
- metaclass.send(:define_method, :body=) do |body|
- @body = body
- end
-
- metaclass.send(:alias_method, body_name, :body)
- metaclass.send(:alias_method, body_name_equals, :body=)
- end
-
- # If applicable, add "media" and "media=" for retrieving and setting
- # the media object for this request.
- # Examples of setting the media object:
- # request.media = object
- # request.execute
- # OR
- # request.media(object).execute
- # Example of retrieving the media object:
- # object = request.media
- if method.media_upload
- metaclass.send(:define_method, :media) do |*args|
- if args.length == 1
- @media = args.first
- return self
- elsif args.length == 0
- return @media
- else
- raise ArgumentError,
- "wrong number of arguments (#{args.length}; expecting 0 or 1)"
- end
- end
-
- metaclass.send(:define_method, :media=) do |media|
- @media = media
- end
- end
- end
-
- ##
- # Returns the parent service capable of executing this request.
- #
- # @return [Google::APIClient::Service] The parent service.
- attr_reader :service
-
- ##
- # Returns the Method instance that describes the API method invoked by
- # the request.
- #
- # @return [Google::APIClient::Method] The API method description.
- attr_reader :method
-
- ##
- # Contains the Hash of parameter names and values to be sent as the
- # parameters for the API call.
- #
- # @return [Hash] The request parameters.
- attr_accessor :parameters
-
- ##
- # Executes the request.
- def execute
- @service.execute(self)
- end
- end
- end
- end
-end
diff --git a/lib/google/api_client/service/resource.rb b/lib/google/api_client/service/resource.rb
deleted file mode 100755
index b493769d4f4..00000000000
--- a/lib/google/api_client/service/resource.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2013 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-module Google
- class APIClient
- class Service
- ##
- # Handles an API resource.
- # Simple class that contains API methods and/or child resources.
- class Resource
- include Google::APIClient::Service::StubGenerator
-
- ##
- # Build a resource.
- # This class should not be directly instantiated in user code; resources
- # are instantiated by the stub generation mechanism on Service creation.
- #
- # @param [Google::APIClient::Service] service
- # The Service instance this resource belongs to.
- # @param [Google::APIClient::API, Google::APIClient::Resource] root
- # The node corresponding to this resource.
- def initialize(service, root)
- @service = service
- generate_call_stubs(service, root)
- end
- end
- end
- end
-end
diff --git a/lib/google/api_client/service/result.rb b/lib/google/api_client/service/result.rb
deleted file mode 100755
index 7957ea6a266..00000000000
--- a/lib/google/api_client/service/result.rb
+++ /dev/null
@@ -1,162 +0,0 @@
-# Copyright 2013 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-module Google
- class APIClient
- class Service
- ##
- # Handles an API result.
- # Wraps around the Google::APIClient::Result class, making it easier to
- # handle the result (e.g. pagination) and keeping it in line with the rest
- # of the Service programming interface.
- class Result
- extend Forwardable
-
- ##
- # Init the result.
- #
- # @param [Google::APIClient::Service::Request] request
- # The original request
- # @param [Google::APIClient::Result] base_result
- # The base result to be wrapped
- def initialize(request, base_result)
- @request = request
- @base_result = base_result
- end
-
- # @!attribute [r] status
- # @return [Fixnum] HTTP status code
- # @!attribute [r] headers
- # @return [Hash] HTTP response headers
- # @!attribute [r] body
- # @return [String] HTTP response body
- def_delegators :@base_result, :status, :headers, :body
-
- # @return [Google::APIClient::Service::Request] Original request object
- attr_reader :request
-
- ##
- # Get the content type of the response
- # @!attribute [r] media_type
- # @return [String]
- # Value of content-type header
- def_delegators :@base_result, :media_type
-
- ##
- # Check if request failed
- #
- # @!attribute [r] error?
- # @return [TrueClass, FalseClass]
- # true if result of operation is an error
- def_delegators :@base_result, :error?
-
- ##
- # Check if request was successful
- #
- # @!attribute [r] success?
- # @return [TrueClass, FalseClass]
- # true if result of operation was successful
- def_delegators :@base_result, :success?
-
- ##
- # Extracts error messages from the response body
- #
- # @!attribute [r] error_message
- # @return [String]
- # error message, if available
- def_delegators :@base_result, :error_message
-
- ##
- # Check for parsable data in response
- #
- # @!attribute [r] data?
- # @return [TrueClass, FalseClass]
- # true if body can be parsed
- def_delegators :@base_result, :data?
-
- ##
- # Return parsed version of the response body.
- #
- # @!attribute [r] data
- # @return [Object, Hash, String]
- # Object if body parsable from API schema, Hash if JSON, raw body if unable to parse
- def_delegators :@base_result, :data
-
- ##
- # Pagination scheme used by this request/response
- #
- # @!attribute [r] pagination_type
- # @return [Symbol]
- # currently always :token
- def_delegators :@base_result, :pagination_type
-
- ##
- # Name of the field that contains the pagination token
- #
- # @!attribute [r] page_token_param
- # @return [String]
- # currently always 'pageToken'
- def_delegators :@base_result, :page_token_param
-
- ##
- # Get the token used for requesting the next page of data
- #
- # @!attribute [r] next_page_token
- # @return [String]
- # next page tokenx =
- def_delegators :@base_result, :next_page_token
-
- ##
- # Get the token used for requesting the previous page of data
- #
- # @!attribute [r] prev_page_token
- # @return [String]
- # previous page token
- def_delegators :@base_result, :prev_page_token
-
- # @!attribute [r] resumable_upload
- def resumable_upload
- # TODO(sgomes): implement resumable_upload for Service::Result
- raise NotImplementedError
- end
-
- ##
- # Build a request for fetching the next page of data
- #
- # @return [Google::APIClient::Service::Request]
- # API request for retrieving next page
- def next_page
- request = @request.clone
- # Make a deep copy of the parameters.
- request.parameters = Marshal.load(Marshal.dump(request.parameters))
- request.parameters[page_token_param] = self.next_page_token
- return request
- end
-
- ##
- # Build a request for fetching the previous page of data
- #
- # @return [Google::APIClient::Service::Request]
- # API request for retrieving previous page
- def prev_page
- request = @request.clone
- # Make a deep copy of the parameters.
- request.parameters = Marshal.load(Marshal.dump(request.parameters))
- request.parameters[page_token_param] = self.prev_page_token
- return request
- end
- end
- end
- end
-end
diff --git a/lib/google/api_client/service/simple_file_store.rb b/lib/google/api_client/service/simple_file_store.rb
deleted file mode 100644
index 216b3fac5ff..00000000000
--- a/lib/google/api_client/service/simple_file_store.rb
+++ /dev/null
@@ -1,151 +0,0 @@
-# Copyright 2013 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-module Google
- class APIClient
- class Service
-
- # Simple file store to be used in the event no ActiveSupport cache store
- # is provided. This is not thread-safe, and does not support a number of
- # features (such as expiration), but it's useful for the simple purpose of
- # caching discovery documents to disk.
- # Implements the basic cache methods of ActiveSupport::Cache::Store in a
- # limited fashion.
- class SimpleFileStore
-
- # Creates a new SimpleFileStore.
- #
- # @param [String] file_path
- # The path to the cache file on disk.
- # @param [Object] options
- # The options to be used with this SimpleFileStore. Not implemented.
- def initialize(file_path, options = nil)
- @file_path = file_path.to_s
- end
-
- # Returns true if a key exists in the cache.
- #
- # @param [String] name
- # The name of the key. Will always be converted to a string.
- # @param [Object] options
- # The options to be used with this query. Not implemented.
- def exist?(name, options = nil)
- read_file
- @cache.nil? ? nil : @cache.include?(name.to_s)
- end
-
- # Fetches data from the cache and returns it, using the given key.
- # If the key is missing and no block is passed, returns nil.
- # If the key is missing and a block is passed, executes the block, sets
- # the key to its value, and returns it.
- #
- # @param [String] name
- # The name of the key. Will always be converted to a string.
- # @param [Object] options
- # The options to be used with this query. Not implemented.
- # @yield [String]
- # optional block with the default value if the key is missing
- def fetch(name, options = nil)
- read_file
- if block_given?
- entry = read(name.to_s, options)
- if entry.nil?
- value = yield name.to_s
- write(name.to_s, value)
- return value
- else
- return entry
- end
- else
- return read(name.to_s, options)
- end
- end
-
- # Fetches data from the cache, using the given key.
- # Returns nil if the key is missing.
- #
- # @param [String] name
- # The name of the key. Will always be converted to a string.
- # @param [Object] options
- # The options to be used with this query. Not implemented.
- def read(name, options = nil)
- read_file
- @cache.nil? ? nil : @cache[name.to_s]
- end
-
- # Writes the value to the cache, with the key.
- #
- # @param [String] name
- # The name of the key. Will always be converted to a string.
- # @param [Object] value
- # The value to be written.
- # @param [Object] options
- # The options to be used with this query. Not implemented.
- def write(name, value, options = nil)
- read_file
- @cache = {} if @cache.nil?
- @cache[name.to_s] = value
- write_file
- return nil
- end
-
- # Deletes an entry in the cache.
- # Returns true if an entry is deleted.
- #
- # @param [String] name
- # The name of the key. Will always be converted to a string.
- # @param [Object] options
- # The options to be used with this query. Not implemented.
- def delete(name, options = nil)
- read_file
- return nil if @cache.nil?
- if @cache.include? name.to_s
- @cache.delete name.to_s
- write_file
- return true
- else
- return nil
- end
- end
-
- protected
-
- # Read the entire cache file from disk.
- # Will avoid reading if there have been no changes.
- def read_file
- if !File.exist? @file_path
- @cache = nil
- else
- # Check for changes after our last read or write.
- if @last_change.nil? || File.mtime(@file_path) > @last_change
- File.open(@file_path) do |file|
- @cache = Marshal.load(file)
- @last_change = file.mtime
- end
- end
- end
- return @cache
- end
-
- # Write the entire cache contents to disk.
- def write_file
- File.open(@file_path, 'w') do |file|
- Marshal.dump(@cache, file)
- end
- @last_change = File.mtime(@file_path)
- end
- end
- end
- end
-end
\ No newline at end of file
diff --git a/lib/google/api_client/service/stub_generator.rb b/lib/google/api_client/service/stub_generator.rb
deleted file mode 100755
index 3c84dddbd2e..00000000000
--- a/lib/google/api_client/service/stub_generator.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# Copyright 2013 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'active_support/inflector'
-
-module Google
- class APIClient
- class Service
- ##
- # Auxiliary mixin to generate resource and method stubs.
- # Used by the Service and Service::Resource classes to generate both
- # top-level and nested resources and methods.
- module StubGenerator
- def generate_call_stubs(service, root)
- metaclass = (class << self; self; end)
-
- # Handle resources.
- root.discovered_resources.each do |resource|
- method_name = ActiveSupport::Inflector.underscore(resource.name).to_sym
- if !self.respond_to?(method_name)
- metaclass.send(:define_method, method_name) do
- Google::APIClient::Service::Resource.new(service, resource)
- end
- end
- end
-
- # Handle methods.
- root.discovered_methods.each do |method|
- method_name = ActiveSupport::Inflector.underscore(method.name).to_sym
- if !self.respond_to?(method_name)
- metaclass.send(:define_method, method_name) do |*args|
- if args.length > 1
- raise ArgumentError,
- "wrong number of arguments (#{args.length} for 1)"
- elsif !args.first.respond_to?(:to_hash) && !args.first.nil?
- raise ArgumentError,
- "expected parameter Hash, got #{args.first.class}"
- else
- return Google::APIClient::Service::Request.new(
- service, method, args.first
- )
- end
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/legacy/google/api_client.rb b/lib/legacy/google/api_client.rb
new file mode 100644
index 00000000000..3162597024c
--- /dev/null
+++ b/lib/legacy/google/api_client.rb
@@ -0,0 +1,753 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+require 'faraday'
+require 'multi_json'
+require 'compat/multi_json'
+require 'stringio'
+require 'retriable'
+
+require 'legacy/google/api_client/version'
+require 'legacy/google/api_client/logging'
+require 'legacy/google/api_client/errors'
+require 'legacy/google/api_client/environment'
+require 'legacy/google/api_client/discovery'
+require 'legacy/google/api_client/request'
+require 'legacy/google/api_client/reference'
+require 'legacy/google/api_client/result'
+require 'legacy/google/api_client/media'
+require 'legacy/google/api_client/service_account'
+require 'legacy/google/api_client/batch'
+require 'legacy/google/api_client/gzip'
+require 'legacy/google/api_client/charset'
+require 'legacy/google/api_client/client_secrets'
+require 'legacy/google/api_client/railtie' if defined?(Rails)
+
+
+module Legacy
+ module Google
+
+ ##
+ # This class manages APIs communication.
+ class APIClient
+ include Legacy::Google::APIClient::Logging
+
+ ##
+ # Creates a new Google API client.
+ #
+ # @param [Hash] options The configuration parameters for the client.
+ # @option options [Symbol, #generate_authenticated_request] :authorization
+ # (:oauth_1)
+ # The authorization mechanism used by the client. The following
+ # mechanisms are supported out-of-the-box:
+ #
+ # :two_legged_oauth_1
+ # :oauth_1
+ # :oauth_2
+ # :google_app_default
+ #
+ # @option options [Boolean] :auto_refresh_token (true)
+ # The setting that controls whether or not the api client attempts to
+ # refresh authorization when a 401 is hit in #execute. If the token does
+ # not support it, this option is ignored.
+ # @option options [String] :application_name
+ # The name of the application using the client.
+ # @option options [String | Array | nil] :scope
+ # The scope(s) used when using google application default credentials
+ # @option options [String] :application_version
+ # The version number of the application using the client.
+ # @option options [String] :user_agent
+ # ("{app_name} google-api-ruby-client/{version} {os_name}/{os_version}")
+ # The user agent used by the client. Most developers will want to
+ # leave this value alone and use the `:application_name` option instead.
+ # @option options [String] :host ("www.googleapis.com")
+ # The API hostname used by the client. This rarely needs to be changed.
+ # @option options [String] :port (443)
+ # The port number used by the client. This rarely needs to be changed.
+ # @option options [String] :discovery_path ("/discovery/v1")
+ # The discovery base path. This rarely needs to be changed.
+ # @option options [String] :ca_file
+ # Optional set of root certificates to use when validating SSL connections.
+ # By default, a bundled set of trusted roots will be used.
+ # @options options[Hash] :force_encoding
+ # Experimental option. True if response body should be force encoded into the charset
+ # specified in the Content-Type header. Mostly intended for compressed content.
+ # @options options[Hash] :faraday_options
+ # Pass through of options to set on the Faraday connection
+ def initialize(options={})
+ logger.debug { "#{self.class} - Initializing client with options #{options}" }
+
+ # Normalize key to String to allow indifferent access.
+ options = options.inject({}) do |accu, (key, value)|
+ accu[key.to_sym] = value
+ accu
+ end
+ # Almost all API usage will have a host of 'www.googleapis.com'.
+ self.host = options[:host] || 'www.googleapis.com'
+ self.port = options[:port] || 443
+ self.discovery_path = options[:discovery_path] || '/discovery/v1'
+
+ # Most developers will want to leave this value alone and use the
+ # application_name option.
+ if options[:application_name]
+ app_name = options[:application_name]
+ app_version = options[:application_version]
+ application_string = "#{app_name}/#{app_version || '0.0.0'}"
+ else
+ logger.warn { "#{self.class} - Please provide :application_name and :application_version when initializing the client" }
+ end
+
+ proxy = options[:proxy] || Object::ENV["http_proxy"]
+
+ self.user_agent = options[:user_agent] || (
+ "#{application_string} " +
+ "google-api-ruby-client/#{Legacy::Google::APIClient::VERSION::STRING} #{ENV::OS_VERSION} (gzip)"
+ ).strip
+ # The writer method understands a few Symbols and will generate useful
+ # default authentication mechanisms.
+ self.authorization =
+ options.key?(:authorization) ? options[:authorization] : :oauth_2
+ if !options['scope'].nil? and self.authorization.respond_to?(:scope=)
+ self.authorization.scope = options['scope']
+ end
+ self.auto_refresh_token = options.fetch(:auto_refresh_token) { true }
+ self.key = options[:key]
+ self.user_ip = options[:user_ip]
+ self.retries = options.fetch(:retries) { 0 }
+ self.expired_auth_retry = options.fetch(:expired_auth_retry) { true }
+ @discovery_uris = {}
+ @discovery_documents = {}
+ @discovered_apis = {}
+ ca_file = options[:ca_file] || File.expand_path('../../../cacerts.pem', __FILE__)
+ self.connection = Faraday.new do |faraday|
+ faraday.response :charset if options[:force_encoding]
+ faraday.response :gzip
+ faraday.options.params_encoder = Faraday::FlatParamsEncoder
+ faraday.ssl.ca_file = ca_file
+ faraday.ssl.verify = true
+ faraday.proxy proxy
+ faraday.adapter Faraday.default_adapter
+ if options[:faraday_option].is_a?(Hash)
+ options[:faraday_option].each_pair do |option, value|
+ faraday.options.send("#{option}=", value)
+ end
+ end
+ end
+ return self
+ end
+
+ ##
+ # Returns the authorization mechanism used by the client.
+ #
+ # @return [#generate_authenticated_request] The authorization mechanism.
+ attr_reader :authorization
+
+ ##
+ # Sets the authorization mechanism used by the client.
+ #
+ # @param [#generate_authenticated_request] new_authorization
+ # The new authorization mechanism.
+ def authorization=(new_authorization)
+ case new_authorization
+ when :oauth_1, :oauth
+ require 'signet/oauth_1/client'
+ # NOTE: Do not rely on this default value, as it may change
+ new_authorization = Signet::OAuth1::Client.new(
+ :temporary_credential_uri =>
+ 'https://www.google.com/accounts/OAuthGetRequestToken',
+ :authorization_uri =>
+ 'https://www.google.com/accounts/OAuthAuthorizeToken',
+ :token_credential_uri =>
+ 'https://www.google.com/accounts/OAuthGetAccessToken',
+ :client_credential_key => 'anonymous',
+ :client_credential_secret => 'anonymous'
+ )
+ when :two_legged_oauth_1, :two_legged_oauth
+ require 'signet/oauth_1/client'
+ # NOTE: Do not rely on this default value, as it may change
+ new_authorization = Signet::OAuth1::Client.new(
+ :client_credential_key => nil,
+ :client_credential_secret => nil,
+ :two_legged => true
+ )
+ when :google_app_default
+ require 'googleauth'
+ new_authorization = Google::Auth.get_application_default
+
+ when :oauth_2
+ require 'signet/oauth_2/client'
+ # NOTE: Do not rely on this default value, as it may change
+ new_authorization = Signet::OAuth2::Client.new(
+ :authorization_uri =>
+ 'https://accounts.google.com/o/oauth2/auth',
+ :token_credential_uri =>
+ 'https://accounts.google.com/o/oauth2/token'
+ )
+ when nil
+ # No authorization mechanism
+ else
+ if !new_authorization.respond_to?(:generate_authenticated_request)
+ raise TypeError,
+ 'Expected authorization mechanism to respond to ' +
+ '#generate_authenticated_request.'
+ end
+ end
+ @authorization = new_authorization
+ return @authorization
+ end
+
+ ##
+ # Default Faraday/HTTP connection.
+ #
+ # @return [Faraday::Connection]
+ attr_accessor :connection
+
+ ##
+ # The setting that controls whether or not the api client attempts to
+ # refresh authorization when a 401 is hit in #execute.
+ #
+ # @return [Boolean]
+ attr_accessor :auto_refresh_token
+
+ ##
+ # The application's API key issued by the API console.
+ #
+ # @return [String] The API key.
+ attr_accessor :key
+
+ ##
+ # The IP address of the user this request is being performed on behalf of.
+ #
+ # @return [String] The user's IP address.
+ attr_accessor :user_ip
+
+ ##
+ # The user agent used by the client.
+ #
+ # @return [String]
+ # The user agent string used in the User-Agent header.
+ attr_accessor :user_agent
+
+ ##
+ # The API hostname used by the client.
+ #
+ # @return [String]
+ # The API hostname. Should almost always be 'www.googleapis.com'.
+ attr_accessor :host
+
+ ##
+ # The port number used by the client.
+ #
+ # @return [String]
+ # The port number. Should almost always be 443.
+ attr_accessor :port
+
+ ##
+ # The base path used by the client for discovery.
+ #
+ # @return [String]
+ # The base path. Should almost always be '/discovery/v1'.
+ attr_accessor :discovery_path
+
+ ##
+ # Number of times to retry on recoverable errors
+ #
+ # @return [FixNum]
+ # Number of retries
+ attr_accessor :retries
+
+ ##
+ # Whether or not an expired auth token should be re-acquired
+ # (and the operation retried) regardless of retries setting
+ # @return [Boolean]
+ # Auto retry on auth expiry
+ attr_accessor :expired_auth_retry
+
+ ##
+ # Returns the URI for the directory document.
+ #
+ # @return [Addressable::URI] The URI of the directory document.
+ def directory_uri
+ return resolve_uri(self.discovery_path + '/apis')
+ end
+
+ ##
+ # Manually registers a URI as a discovery document for a specific version
+ # of an API.
+ #
+ # @param [String, Symbol] api The API name.
+ # @param [String] version The desired version of the API.
+ # @param [Addressable::URI] uri The URI of the discovery document.
+ # @return [Legacy::Google::APIClient::API] The service object.
+ def register_discovery_uri(api, version, uri)
+ api = api.to_s
+ version = version || 'v1'
+ @discovery_uris["#{api}:#{version}"] = uri
+ discovered_api(api, version)
+ end
+
+ ##
+ # Returns the URI for the discovery document.
+ #
+ # @param [String, Symbol] api The API name.
+ # @param [String] version The desired version of the API.
+ # @return [Addressable::URI] The URI of the discovery document.
+ def discovery_uri(api, version=nil)
+ api = api.to_s
+ version = version || 'v1'
+ return @discovery_uris["#{api}:#{version}"] ||= (
+ resolve_uri(
+ self.discovery_path + '/apis/{api}/{version}/rest',
+ 'api' => api,
+ 'version' => version
+ )
+ )
+ end
+
+ ##
+ # Manually registers a pre-loaded discovery document for a specific version
+ # of an API.
+ #
+ # @param [String, Symbol] api The API name.
+ # @param [String] version The desired version of the API.
+ # @param [String, StringIO] discovery_document
+ # The contents of the discovery document.
+ # @return [Legacy::Google::APIClient::API] The service object.
+ def register_discovery_document(api, version, discovery_document)
+ api = api.to_s
+ version = version || 'v1'
+ if discovery_document.kind_of?(StringIO)
+ discovery_document.rewind
+ discovery_document = discovery_document.string
+ elsif discovery_document.respond_to?(:to_str)
+ discovery_document = discovery_document.to_str
+ else
+ raise TypeError,
+ "Expected String or StringIO, got #{discovery_document.class}."
+ end
+ @discovery_documents["#{api}:#{version}"] =
+ MultiJson.load(discovery_document)
+ discovered_api(api, version)
+ end
+
+ ##
+ # Returns the parsed directory document.
+ #
+ # @return [Hash] The parsed JSON from the directory document.
+ def directory_document
+ return @directory_document ||= (begin
+ response = self.execute!(
+ :http_method => :get,
+ :uri => self.directory_uri,
+ :authenticated => false
+ )
+ response.data
+ end)
+ end
+
+ ##
+ # Returns the parsed discovery document.
+ #
+ # @param [String, Symbol] api The API name.
+ # @param [String] version The desired version of the API.
+ # @return [Hash] The parsed JSON from the discovery document.
+ def discovery_document(api, version=nil)
+ api = api.to_s
+ version = version || 'v1'
+ return @discovery_documents["#{api}:#{version}"] ||= (begin
+ response = self.execute!(
+ :http_method => :get,
+ :uri => self.discovery_uri(api, version),
+ :authenticated => false
+ )
+ response.data
+ end)
+ end
+
+ ##
+ # Returns all APIs published in the directory document.
+ #
+ # @return [Array] The list of available APIs.
+ def discovered_apis
+ @directory_apis ||= (begin
+ document_base = self.directory_uri
+ if self.directory_document && self.directory_document['items']
+ self.directory_document['items'].map do |discovery_document|
+ Legacy::Google::APIClient::API.new(
+ document_base,
+ discovery_document
+ )
+ end
+ else
+ []
+ end
+ end)
+ end
+
+ ##
+ # Returns the service object for a given service name and service version.
+ #
+ # @param [String, Symbol] api The API name.
+ # @param [String] version The desired version of the API.
+ #
+ # @return [Legacy::Google::APIClient::API] The service object.
+ def discovered_api(api, version=nil)
+ if !api.kind_of?(String) && !api.kind_of?(Symbol)
+ raise TypeError,
+ "Expected String or Symbol, got #{api.class}."
+ end
+ api = api.to_s
+ version = version || 'v1'
+ return @discovered_apis["#{api}:#{version}"] ||= begin
+ document_base = self.discovery_uri(api, version)
+ discovery_document = self.discovery_document(api, version)
+ if document_base && discovery_document
+ Legacy::Google::APIClient::API.new(
+ document_base,
+ discovery_document
+ )
+ else
+ nil
+ end
+ end
+ end
+
+ ##
+ # Returns the method object for a given RPC name and service version.
+ #
+ # @param [String, Symbol] rpc_name The RPC name of the desired method.
+ # @param [String, Symbol] api The API the method is within.
+ # @param [String] version The desired version of the API.
+ #
+ # @return [Legacy::Google::APIClient::Method] The method object.
+ def discovered_method(rpc_name, api, version=nil)
+ if !rpc_name.kind_of?(String) && !rpc_name.kind_of?(Symbol)
+ raise TypeError,
+ "Expected String or Symbol, got #{rpc_name.class}."
+ end
+ rpc_name = rpc_name.to_s
+ api = api.to_s
+ version = version || 'v1'
+ service = self.discovered_api(api, version)
+ if service.to_h[rpc_name]
+ return service.to_h[rpc_name]
+ else
+ return nil
+ end
+ end
+
+ ##
+ # Returns the service object with the highest version number.
+ #
+ # @note Warning: This method should be used with great care.
+ # As APIs are updated, minor differences between versions may cause
+ # incompatibilities. Requesting a specific version will avoid this issue.
+ #
+ # @param [String, Symbol] api The name of the service.
+ #
+ # @return [Legacy::Google::APIClient::API] The service object.
+ def preferred_version(api)
+ if !api.kind_of?(String) && !api.kind_of?(Symbol)
+ raise TypeError,
+ "Expected String or Symbol, got #{api.class}."
+ end
+ api = api.to_s
+ return self.discovered_apis.detect do |a|
+ a.name == api && a.preferred == true
+ end
+ end
+
+ ##
+ # Verifies an ID token against a server certificate. Used to ensure that
+ # an ID token supplied by an untrusted client-side mechanism is valid.
+ # Raises an error if the token is invalid or missing.
+ #
+ # @deprecated Use the google-id-token gem for verifying JWTs
+ def verify_id_token!
+ require 'jwt'
+ require 'openssl'
+ @certificates ||= {}
+ if !self.authorization.respond_to?(:id_token)
+ raise ArgumentError, (
+ "Current authorization mechanism does not support ID tokens: " +
+ "#{self.authorization.class.to_s}"
+ )
+ elsif !self.authorization.id_token
+ raise ArgumentError, (
+ "Could not verify ID token, ID token missing. " +
+ "Scopes were: #{self.authorization.scope.inspect}"
+ )
+ else
+ check_cached_certs = lambda do
+ valid = false
+ for _key, cert in @certificates
+ begin
+ self.authorization.decoded_id_token(cert.public_key)
+ valid = true
+ rescue JWT::DecodeError, Signet::UnsafeOperationError
+ # Expected exception. Ignore, ID token has not been validated.
+ end
+ end
+ valid
+ end
+ if check_cached_certs.call()
+ return true
+ end
+ response = self.execute!(
+ :http_method => :get,
+ :uri => 'https://www.googleapis.com/oauth2/v1/certs',
+ :authenticated => false
+ )
+ @certificates.merge!(
+ Hash[MultiJson.load(response.body).map do |key, cert|
+ [key, OpenSSL::X509::Certificate.new(cert)]
+ end]
+ )
+ if check_cached_certs.call()
+ return true
+ else
+ raise InvalidIDTokenError,
+ "Could not verify ID token against any available certificate."
+ end
+ end
+ return nil
+ end
+
+ ##
+ # Generates a request.
+ #
+ # @option options [Legacy::Google::APIClient::Method] :api_method
+ # The method object or the RPC name of the method being executed.
+ # @option options [Hash, Array] :parameters
+ # The parameters to send to the method.
+ # @option options [Hash, Array] :headers The HTTP headers for the request.
+ # @option options [String] :body The body of the request.
+ # @option options [String] :version ("v1")
+ # The service version. Only used if `api_method` is a `String`.
+ # @option options [#generate_authenticated_request] :authorization
+ # The authorization mechanism for the response. Used only if
+ # `:authenticated` is `true`.
+ # @option options [TrueClass, FalseClass] :authenticated (true)
+ # `true` if the request must be signed or somehow
+ # authenticated, `false` otherwise.
+ #
+ # @return [Legacy::Google::APIClient::Reference] The generated request.
+ #
+ # @example
+ # request = client.generate_request(
+ # :api_method => 'plus.activities.list',
+ # :parameters =>
+ # {'collection' => 'public', 'userId' => 'me'}
+ # )
+ def generate_request(options={})
+ options = {
+ :api_client => self
+ }.merge(options)
+ return Legacy::Google::APIClient::Request.new(options)
+ end
+
+ ##
+ # Executes a request, wrapping it in a Result object.
+ #
+ # @param [Legacy::Google::APIClient::Request, Hash, Array] params
+ # Either a Legacy::Google::APIClient::Request, a Hash, or an Array.
+ #
+ # If a Legacy::Google::APIClient::Request, no other parameters are expected.
+ #
+ # If a Hash, the below parameters are handled. If an Array, the
+ # parameters are assumed to be in the below order:
+ #
+ # - (Legacy::Google::APIClient::Method) api_method:
+ # The method object or the RPC name of the method being executed.
+ # - (Hash, Array) parameters:
+ # The parameters to send to the method.
+ # - (String) body: The body of the request.
+ # - (Hash, Array) headers: The HTTP headers for the request.
+ # - (Hash) options: A set of options for the request, of which:
+ # - (#generate_authenticated_request) :authorization (default: true) -
+ # The authorization mechanism for the response. Used only if
+ # `:authenticated` is `true`.
+ # - (TrueClass, FalseClass) :authenticated (default: true) -
+ # `true` if the request must be signed or somehow
+ # authenticated, `false` otherwise.
+ # - (TrueClass, FalseClass) :gzip (default: true) -
+ # `true` if gzip enabled, `false` otherwise.
+ # - (FixNum) :retries -
+ # # of times to retry on recoverable errors
+ #
+ # @return [Legacy::Google::APIClient::Result] The result from the API, nil if batch.
+ #
+ # @example
+ # result = client.execute(batch_request)
+ #
+ # @example
+ # plus = client.discovered_api('plus')
+ # result = client.execute(
+ # :api_method => plus.activities.list,
+ # :parameters => {'collection' => 'public', 'userId' => 'me'}
+ # )
+ #
+ # @see Legacy::Google::APIClient#generate_request
+ def execute!(*params)
+ if params.first.kind_of?(Legacy::Google::APIClient::Request)
+ request = params.shift
+ options = params.shift || {}
+ else
+ # This block of code allows us to accept multiple parameter passing
+ # styles, and maintaining some backwards compatibility.
+ #
+ # Note: I'm extremely tempted to deprecate this style of execute call.
+ if params.last.respond_to?(:to_hash) && params.size == 1
+ options = params.pop
+ else
+ options = {}
+ end
+
+ options[:api_method] = params.shift if params.size > 0
+ options[:parameters] = params.shift if params.size > 0
+ options[:body] = params.shift if params.size > 0
+ options[:headers] = params.shift if params.size > 0
+ options.update(params.shift) if params.size > 0
+ request = self.generate_request(options)
+ end
+
+ request.headers['User-Agent'] ||= '' + self.user_agent unless self.user_agent.nil?
+ request.headers['Accept-Encoding'] ||= 'gzip' unless options[:gzip] == false
+ request.headers['Content-Type'] ||= ''
+ request.parameters['key'] ||= self.key unless self.key.nil?
+ request.parameters['userIp'] ||= self.user_ip unless self.user_ip.nil?
+
+ connection = options[:connection] || self.connection
+ request.authorization = options[:authorization] || self.authorization unless options[:authenticated] == false
+
+ tries = 1 + (options[:retries] || self.retries)
+ attempt = 0
+
+ Retriable.retriable :tries => tries,
+ :on => [TransmissionError],
+ :on_retry => client_error_handler,
+ :interval => lambda {|attempts| (2 ** attempts) + rand} do
+ attempt += 1
+
+ # This 2nd level retriable only catches auth errors, and supports 1 retry, which allows
+ # auth to be re-attempted without having to retry all sorts of other failures like
+ # NotFound, etc
+ Retriable.retriable :tries => ((expired_auth_retry || tries > 1) && attempt == 1) ? 2 : 1,
+ :on => [AuthorizationError],
+ :on_retry => authorization_error_handler(request.authorization) do
+ result = request.send(connection, true)
+
+ case result.status
+ when 200...300
+ result
+ when 301, 302, 303, 307
+ request = generate_request(request.to_hash.merge({
+ :uri => result.headers['location'],
+ :api_method => nil
+ }))
+ raise RedirectError.new(result.headers['location'], result)
+ when 401
+ raise AuthorizationError.new(result.error_message || 'Invalid/Expired Authentication', result)
+ when 400, 402...500
+ raise ClientError.new(result.error_message || "A client error has occurred", result)
+ when 500...600
+ raise ServerError.new(result.error_message || "A server error has occurred", result)
+ else
+ raise TransmissionError.new(result.error_message || "A transmission error has occurred", result)
+ end
+ end
+ end
+ end
+
+ ##
+ # Same as Legacy::Google::APIClient#execute!, but does not raise an exception for
+ # normal API errros.
+ #
+ # @see Legacy::Google::APIClient#execute
+ def execute(*params)
+ begin
+ return self.execute!(*params)
+ rescue TransmissionError => e
+ return e.result
+ end
+ end
+
+ protected
+
+ ##
+ # Resolves a URI template against the client's configured base.
+ #
+ # @api private
+ # @param [String, Addressable::URI, Addressable::Template] template
+ # The template to resolve.
+ # @param [Hash] mapping The mapping that corresponds to the template.
+ # @return [Addressable::URI] The expanded URI.
+ def resolve_uri(template, mapping={})
+ @base_uri ||= Addressable::URI.new(
+ :scheme => 'https',
+ :host => self.host,
+ :port => self.port
+ ).normalize
+ template = if template.kind_of?(Addressable::Template)
+ template.pattern
+ elsif template.respond_to?(:to_str)
+ template.to_str
+ else
+ raise TypeError,
+ "Expected String, Addressable::URI, or Addressable::Template, " +
+ "got #{template.class}."
+ end
+ return Addressable::Template.new(@base_uri + template).expand(mapping)
+ end
+
+
+ ##
+ # Returns on proc for special processing of retries for authorization errors
+ # Only 401s should be retried and only if the credentials are refreshable
+ #
+ # @param [#fetch_access_token!] authorization
+ # OAuth 2 credentials
+ # @return [Proc]
+ def authorization_error_handler(authorization)
+ can_refresh = authorization.respond_to?(:refresh_token) && auto_refresh_token
+ Proc.new do |exception, tries|
+ next unless exception.kind_of?(AuthorizationError)
+ if can_refresh
+ begin
+ logger.debug("Attempting refresh of access token & retry of request")
+ authorization.fetch_access_token!
+ next
+ rescue Signet::AuthorizationError
+ end
+ end
+ raise exception
+ end
+ end
+
+ ##
+ # Returns on proc for special processing of retries as not all client errors
+ # are recoverable. Only 401s should be retried (via authorization_error_handler)
+ #
+ # @return [Proc]
+ def client_error_handler
+ Proc.new do |exception, tries|
+ raise exception if exception.kind_of?(ClientError)
+ end
+ end
+
+ end
+
+ end
+end
diff --git a/lib/google/api_client/auth/compute_service_account.rb b/lib/legacy/google/api_client/auth/compute_service_account.rb
similarity index 59%
rename from lib/google/api_client/auth/compute_service_account.rb
rename to lib/legacy/google/api_client/auth/compute_service_account.rb
index 118f1e6eb1f..2943e064de7 100644
--- a/lib/google/api_client/auth/compute_service_account.rb
+++ b/lib/legacy/google/api_client/auth/compute_service_account.rb
@@ -15,13 +15,15 @@
require 'faraday'
require 'signet/oauth_2/client'
-module Google
- class APIClient
- class ComputeServiceAccount < Signet::OAuth2::Client
- def fetch_access_token(options={})
- connection = options[:connection] || Faraday.default_connection
- response = connection.get 'http://metadata/computeMetadata/v1beta1/instance/service-accounts/default/token'
- Signet::OAuth2.parse_credentials(response.body, response.headers['content-type'])
+module Legacy
+ module Google
+ class APIClient
+ class ComputeServiceAccount < Signet::OAuth2::Client
+ def fetch_access_token(options={})
+ connection = options[:connection] || Faraday.default_connection
+ response = connection.get 'http://metadata/computeMetadata/v1beta1/instance/service-accounts/default/token'
+ Signet::OAuth2.parse_credentials(response.body, response.headers['content-type'])
+ end
end
end
end
diff --git a/lib/legacy/google/api_client/auth/file_storage.rb b/lib/legacy/google/api_client/auth/file_storage.rb
new file mode 100644
index 00000000000..a980f2a6c7d
--- /dev/null
+++ b/lib/legacy/google/api_client/auth/file_storage.rb
@@ -0,0 +1,61 @@
+# Copyright 2013 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'signet/oauth_2/client'
+require_relative 'storage'
+require_relative 'storages/file_store'
+
+module Legacy
+ module Google
+ class APIClient
+
+ ##
+ # Represents cached OAuth 2 tokens stored on local disk in a
+ # JSON serialized file. Meant to resemble the serialized format
+ # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
+ #
+ # @deprecated
+ # Use {Legacy::Google::APIClient::Storage} and {Legacy::Google::APIClient::FileStore} instead
+ #
+ class FileStorage
+
+ attr_accessor :storage
+
+ def initialize(path)
+ store = Legacy::Google::APIClient::FileStore.new(path)
+ @storage = Legacy::Google::APIClient::Storage.new(store)
+ @storage.authorize
+ end
+
+ def load_credentials
+ storage.authorize
+ end
+
+ def authorization
+ storage.authorization
+ end
+
+ ##
+ # Write the credentials to the specified file.
+ #
+ # @param [Signet::OAuth2::Client] authorization
+ # Optional authorization instance. If not provided, the authorization
+ # already associated with this instance will be written.
+ def write_credentials(auth=nil)
+ storage.write_credentials(auth)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/auth/installed_app.rb b/lib/legacy/google/api_client/auth/installed_app.rb
new file mode 100644
index 00000000000..1deea5ac7c5
--- /dev/null
+++ b/lib/legacy/google/api_client/auth/installed_app.rb
@@ -0,0 +1,127 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'webrick'
+require 'launchy'
+
+module Legacy
+ module Google
+ class APIClient
+
+ # Small helper for the sample apps for performing OAuth 2.0 flows from the command
+ # line or in any other installed app environment.
+ #
+ # @example
+ #
+ # client = Legacy::Google::APIClient.new
+ # flow = Legacy::Google::APIClient::InstalledAppFlow.new(
+ # :client_id => '691380668085.apps.googleusercontent.com',
+ # :client_secret => '...',
+ # :scope => 'https://www.googleapis.com/auth/drive'
+ # )
+ # client.authorization = flow.authorize
+ #
+ class InstalledAppFlow
+
+ RESPONSE_BODY = <<-HTML
+
+
+
+
+ You may close this window.
+
+ HTML
+
+ ##
+ # Configure the flow
+ #
+ # @param [Hash] options The configuration parameters for the client.
+ # @option options [Fixnum] :port
+ # Port to run the embedded server on. Defaults to 9292
+ # @option options [String] :client_id
+ # A unique identifier issued to the client to identify itself to the
+ # authorization server.
+ # @option options [String] :client_secret
+ # A shared symmetric secret issued by the authorization server,
+ # which is used to authenticate the client.
+ # @option options [String] :scope
+ # The scope of the access request, expressed either as an Array
+ # or as a space-delimited String.
+ #
+ # @see Signet::OAuth2::Client
+ def initialize(options)
+ @port = options[:port] || 9292
+ @authorization = Signet::OAuth2::Client.new({
+ :authorization_uri => 'https://accounts.google.com/o/oauth2/auth',
+ :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
+ :redirect_uri => "http://localhost:#{@port}/"}.update(options)
+ )
+ end
+
+ ##
+ # Request authorization. Opens a browser and waits for response.
+ #
+ # @param [Legacy::Google::APIClient::Storage] storage
+ # Optional object that responds to :write_credentials, used to serialize
+ # the OAuth 2 credentials after completing the flow.
+ #
+ # @return [Signet::OAuth2::Client]
+ # Authorization instance, nil if user cancelled.
+ def authorize(storage=nil)
+ auth = @authorization
+
+ server = WEBrick::HTTPServer.new(
+ :Port => @port,
+ :BindAddress =>"localhost",
+ :Logger => WEBrick::Log.new(STDOUT, 0),
+ :AccessLog => []
+ )
+ begin
+ trap("INT") { server.shutdown }
+
+ server.mount_proc '/' do |req, res|
+ auth.code = req.query['code']
+ if auth.code
+ auth.fetch_access_token!
+ end
+ res.status = WEBrick::HTTPStatus::RC_ACCEPTED
+ res.body = RESPONSE_BODY
+ server.stop
+ end
+
+ Launchy.open(auth.authorization_uri.to_s)
+ server.start
+ ensure
+ server.shutdown
+ end
+ if @authorization.access_token
+ if storage.respond_to?(:write_credentials)
+ storage.write_credentials(@authorization)
+ end
+ return @authorization
+ else
+ return nil
+ end
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/auth/jwt_asserter.rb b/lib/legacy/google/api_client/auth/jwt_asserter.rb
new file mode 100644
index 00000000000..5ceba58ae33
--- /dev/null
+++ b/lib/legacy/google/api_client/auth/jwt_asserter.rb
@@ -0,0 +1,128 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'jwt'
+require 'signet/oauth_2/client'
+require 'delegate'
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # Generates access tokens using the JWT assertion profile. Requires a
+ # service account & access to the private key.
+ #
+ # @example Using Signet
+ #
+ # key = Legacy::Google::APIClient::KeyUtils.load_from_pkcs12('client.p12', 'notasecret')
+ # client.authorization = Signet::OAuth2::Client.new(
+ # :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
+ # :audience => 'https://accounts.google.com/o/oauth2/token',
+ # :scope => 'https://www.googleapis.com/auth/prediction',
+ # :issuer => '123456-abcdef@developer.gserviceaccount.com',
+ # :signing_key => key)
+ # client.authorization.fetch_access_token!
+ # client.execute(...)
+ #
+ # @deprecated
+ # Service accounts are now supported directly in Signet
+ # @see https://developers.google.com/accounts/docs/OAuth2ServiceAccount
+ class JWTAsserter
+ # @return [String] ID/email of the issuing party
+ attr_accessor :issuer
+ # @return [Fixnum] How long, in seconds, the assertion is valid for
+ attr_accessor :expiry
+ # @return [Fixnum] Seconds to expand the issued at/expiry window to account for clock skew
+ attr_accessor :skew
+ # @return [String] Scopes to authorize
+ attr_reader :scope
+ # @return [String,OpenSSL::PKey] key for signing assertions
+ attr_writer :key
+ # @return [String] Algorithm used for signing
+ attr_accessor :algorithm
+
+ ##
+ # Initializes the asserter for a service account.
+ #
+ # @param [String] issuer
+ # Name/ID of the client issuing the assertion
+ # @param [String, Array] scope
+ # Scopes to authorize. May be a space delimited string or array of strings
+ # @param [String,OpenSSL::PKey] key
+ # Key for signing assertions
+ # @param [String] algorithm
+ # Algorithm to use, either 'RS256' for RSA with SHA-256
+ # or 'HS256' for HMAC with SHA-256
+ def initialize(issuer, scope, key, algorithm = "RS256")
+ self.issuer = issuer
+ self.scope = scope
+ self.expiry = 60 # 1 min default
+ self.skew = 60
+ self.key = key
+ self.algorithm = algorithm
+ end
+
+ ##
+ # Set the scopes to authorize
+ #
+ # @param [String, Array] new_scope
+ # Scopes to authorize. May be a space delimited string or array of strings
+ def scope=(new_scope)
+ case new_scope
+ when Array
+ @scope = new_scope.join(' ')
+ when String
+ @scope = new_scope
+ when nil
+ @scope = ''
+ else
+ raise TypeError, "Expected Array or String, got #{new_scope.class}"
+ end
+ end
+
+ ##
+ # Request a new access token.
+ #
+ # @param [String] person
+ # Email address of a user, if requesting a token to act on their behalf
+ # @param [Hash] options
+ # Pass through to Signet::OAuth2::Client.fetch_access_token
+ # @return [Signet::OAuth2::Client] Access token
+ #
+ # @see Signet::OAuth2::Client.fetch_access_token!
+ def authorize(person = nil, options={})
+ authorization = self.to_authorization(person)
+ authorization.fetch_access_token!(options)
+ return authorization
+ end
+
+ ##
+ # Builds a Signet OAuth2 client
+ #
+ # @return [Signet::OAuth2::Client] Access token
+ def to_authorization(person = nil)
+ return Signet::OAuth2::Client.new(
+ :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
+ :audience => 'https://accounts.google.com/o/oauth2/token',
+ :scope => self.scope,
+ :issuer => @issuer,
+ :signing_key => @key,
+ :signing_algorithm => @algorithm,
+ :person => person
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/auth/key_utils.rb b/lib/legacy/google/api_client/auth/key_utils.rb
new file mode 100644
index 00000000000..0582fd3622d
--- /dev/null
+++ b/lib/legacy/google/api_client/auth/key_utils.rb
@@ -0,0 +1,95 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # Helper for loading keys from the PKCS12 files downloaded when
+ # setting up service accounts at the APIs Console.
+ #
+ module KeyUtils
+ ##
+ # Loads a key from PKCS12 file, assuming a single private key
+ # is present.
+ #
+ # @param [String] keyfile
+ # Path of the PKCS12 file to load. If not a path to an actual file,
+ # assumes the string is the content of the file itself.
+ # @param [String] passphrase
+ # Passphrase for unlocking the private key
+ #
+ # @return [OpenSSL::PKey] The private key for signing assertions.
+ def self.load_from_pkcs12(keyfile, passphrase)
+ load_key(keyfile, passphrase) do |content, pass_phrase|
+ OpenSSL::PKCS12.new(content, pass_phrase).key
+ end
+ end
+
+
+ ##
+ # Loads a key from a PEM file.
+ #
+ # @param [String] keyfile
+ # Path of the PEM file to load. If not a path to an actual file,
+ # assumes the string is the content of the file itself.
+ # @param [String] passphrase
+ # Passphrase for unlocking the private key
+ #
+ # @return [OpenSSL::PKey] The private key for signing assertions.
+ #
+ def self.load_from_pem(keyfile, passphrase)
+ load_key(keyfile, passphrase) do | content, pass_phrase|
+ OpenSSL::PKey::RSA.new(content, pass_phrase)
+ end
+ end
+
+ private
+
+ ##
+ # Helper for loading keys from file or memory. Accepts a block
+ # to handle the specific file format.
+ #
+ # @param [String] keyfile
+ # Path of thefile to load. If not a path to an actual file,
+ # assumes the string is the content of the file itself.
+ # @param [String] passphrase
+ # Passphrase for unlocking the private key
+ #
+ # @yield [String, String]
+ # Key file & passphrase to extract key from
+ # @yieldparam [String] keyfile
+ # Contents of the file
+ # @yieldparam [String] passphrase
+ # Passphrase to unlock key
+ # @yieldreturn [OpenSSL::PKey]
+ # Private key
+ #
+ # @return [OpenSSL::PKey] The private key for signing assertions.
+ def self.load_key(keyfile, passphrase, &block)
+ begin
+ begin
+ content = File.open(keyfile, 'rb') { |io| io.read }
+ rescue
+ content = keyfile
+ end
+ block.call(content, passphrase)
+ rescue OpenSSL::OpenSSLError
+ raise ArgumentError.new("Invalid keyfile or passphrase")
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/auth/pkcs12.rb b/lib/legacy/google/api_client/auth/pkcs12.rb
new file mode 100644
index 00000000000..f882279a8fd
--- /dev/null
+++ b/lib/legacy/google/api_client/auth/pkcs12.rb
@@ -0,0 +1,44 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'legacy/google/api_client/auth/key_utils'
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # Helper for loading keys from the PKCS12 files downloaded when
+ # setting up service accounts at the APIs Console.
+ #
+ module PKCS12
+ ##
+ # Loads a key from PKCS12 file, assuming a single private key
+ # is present.
+ #
+ # @param [String] keyfile
+ # Path of the PKCS12 file to load. If not a path to an actual file,
+ # assumes the string is the content of the file itself.
+ # @param [String] passphrase
+ # Passphrase for unlocking the private key
+ #
+ # @return [OpenSSL::PKey] The private key for signing assertions.
+ # @deprecated
+ # Use {Legacy::Google::APIClient::KeyUtils} instead
+ def self.load_key(keyfile, passphrase)
+ KeyUtils.load_from_pkcs12(keyfile, passphrase)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/auth/storage.rb b/lib/legacy/google/api_client/auth/storage.rb
new file mode 100644
index 00000000000..0be27185505
--- /dev/null
+++ b/lib/legacy/google/api_client/auth/storage.rb
@@ -0,0 +1,104 @@
+# Copyright 2013 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'signet/oauth_2/client'
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # Represents cached OAuth 2 tokens stored on local disk in a
+ # JSON serialized file. Meant to resemble the serialized format
+ # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
+ #
+ class Storage
+
+ AUTHORIZATION_URI = 'https://accounts.google.com/o/oauth2/auth'
+ TOKEN_CREDENTIAL_URI = 'https://accounts.google.com/o/oauth2/token'
+
+ # @return [Object] Storage object.
+ attr_accessor :store
+
+ # @return [Signet::OAuth2::Client]
+ attr_reader :authorization
+
+ ##
+ # Initializes the Storage object.
+ #
+ # @params [Object] Storage object
+ def initialize(store)
+ @store= store
+ @authorization = nil
+ end
+
+ ##
+ # Write the credentials to the specified store.
+ #
+ # @params [Signet::OAuth2::Client] authorization
+ # Optional authorization instance. If not provided, the authorization
+ # already associated with this instance will be written.
+ def write_credentials(authorization=nil)
+ @authorization = authorization if authorization
+ if @authorization.respond_to?(:refresh_token) && @authorization.refresh_token
+ store.write_credentials(credentials_hash)
+ end
+ end
+
+ ##
+ # Loads credentials and authorizes an client.
+ # @return [Object] Signet::OAuth2::Client or NIL
+ def authorize
+ @authorization = nil
+ cached_credentials = load_credentials
+ if cached_credentials && cached_credentials.size > 0
+ @authorization = Signet::OAuth2::Client.new(cached_credentials)
+ @authorization.issued_at = Time.at(cached_credentials['issued_at'].to_i)
+ self.refresh_authorization if @authorization.expired?
+ end
+ return @authorization
+ end
+
+ ##
+ # refresh credentials and save them to store
+ def refresh_authorization
+ authorization.refresh!
+ self.write_credentials
+ end
+
+ private
+
+ ##
+ # Attempt to read in credentials from the specified store.
+ def load_credentials
+ store.load_credentials
+ end
+
+ ##
+ # @return [Hash] with credentials
+ def credentials_hash
+ {
+ :access_token => authorization.access_token,
+ :authorization_uri => AUTHORIZATION_URI,
+ :client_id => authorization.client_id,
+ :client_secret => authorization.client_secret,
+ :expires_in => authorization.expires_in,
+ :refresh_token => authorization.refresh_token,
+ :token_credential_uri => TOKEN_CREDENTIAL_URI,
+ :issued_at => authorization.issued_at.to_i
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/auth/storages/file_store.rb b/lib/legacy/google/api_client/auth/storages/file_store.rb
new file mode 100644
index 00000000000..5ad42329e1b
--- /dev/null
+++ b/lib/legacy/google/api_client/auth/storages/file_store.rb
@@ -0,0 +1,60 @@
+# Copyright 2013 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'json'
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # Represents cached OAuth 2 tokens stored on local disk in a
+ # JSON serialized file. Meant to resemble the serialized format
+ # http://google-api-python-client.googlecode.com/hg/docs/epy/oauth2client.file.Storage-class.html
+ #
+ class FileStore
+
+ attr_accessor :path
+
+ ##
+ # Initializes the FileStorage object.
+ #
+ # @param [String] path
+ # Path to the credentials file.
+ def initialize(path)
+ @path= path
+ end
+
+ ##
+ # Attempt to read in credentials from the specified file.
+ def load_credentials
+ open(path, 'r') { |f| JSON.parse(f.read) }
+ rescue
+ nil
+ end
+
+ ##
+ # Write the credentials to the specified file.
+ #
+ # @param [Signet::OAuth2::Client] authorization
+ # Optional authorization instance. If not provided, the authorization
+ # already associated with this instance will be written.
+ def write_credentials(credentials_hash)
+ open(self.path, 'w+') do |f|
+ f.write(credentials_hash.to_json)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/auth/storages/redis_store.rb b/lib/legacy/google/api_client/auth/storages/redis_store.rb
new file mode 100644
index 00000000000..94e7be4d7ff
--- /dev/null
+++ b/lib/legacy/google/api_client/auth/storages/redis_store.rb
@@ -0,0 +1,56 @@
+# Copyright 2013 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'json'
+
+module Legacy
+ module Google
+ class APIClient
+ class RedisStore
+
+ DEFAULT_REDIS_CREDENTIALS_KEY = "google_api_credentials"
+
+ attr_accessor :redis
+
+ ##
+ # Initializes the RedisStore object.
+ #
+ # @params [Object] Redis instance
+ def initialize(redis, key = nil)
+ @redis= redis
+ @redis_credentials_key = key
+ end
+
+ ##
+ # Attempt to read in credentials from redis.
+ def load_credentials
+ credentials = redis.get redis_credentials_key
+ JSON.parse(credentials) if credentials
+ end
+
+ def redis_credentials_key
+ @redis_credentials_key || DEFAULT_REDIS_CREDENTIALS_KEY
+ end
+
+ ##
+ # Write the credentials to redis.
+ #
+ # @params [Hash] credentials
+ def write_credentials(credentials_hash)
+ redis.set(redis_credentials_key, credentials_hash.to_json)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/batch.rb b/lib/legacy/google/api_client/batch.rb
new file mode 100644
index 00000000000..c1ece35bf93
--- /dev/null
+++ b/lib/legacy/google/api_client/batch.rb
@@ -0,0 +1,328 @@
+# Copyright 2012 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'addressable/uri'
+require 'legacy/google/api_client/reference'
+require 'securerandom'
+
+module Legacy
+ module Google
+ class APIClient
+
+ ##
+ # Helper class to contain a response to an individual batched call.
+ #
+ # @api private
+ class BatchedCallResponse
+ # @return [String] UUID of the call
+ attr_reader :call_id
+ # @return [Fixnum] HTTP status code
+ attr_accessor :status
+ # @return [Hash] HTTP response headers
+ attr_accessor :headers
+ # @return [String] HTTP response body
+ attr_accessor :body
+
+ ##
+ # Initialize the call response
+ #
+ # @param [String] call_id
+ # UUID of the original call
+ # @param [Fixnum] status
+ # HTTP status
+ # @param [Hash] headers
+ # HTTP response headers
+ # @param [#read, #to_str] body
+ # Response body
+ def initialize(call_id, status = nil, headers = nil, body = nil)
+ @call_id, @status, @headers, @body = call_id, status, headers, body
+ end
+ end
+
+ # Wraps multiple API calls into a single over-the-wire HTTP request.
+ #
+ # @example
+ #
+ # client = Legacy::Google::APIClient.new
+ # urlshortener = client.discovered_api('urlshortener')
+ # batch = Legacy::Google::APIClient::BatchRequest.new do |result|
+ # puts result.data
+ # end
+ #
+ # batch.add(:api_method => urlshortener.url.insert, :body_object => { 'longUrl' => 'http://example.com/foo' })
+ # batch.add(:api_method => urlshortener.url.insert, :body_object => { 'longUrl' => 'http://example.com/bar' })
+ #
+ # client.execute(batch)
+ #
+ class BatchRequest < Request
+ BATCH_BOUNDARY = "-----------RubyApiBatchRequest".freeze
+
+ # @api private
+ # @return [Array<(String,Legacy::Google::APIClient::Request,Proc)] List of API calls in the batch
+ attr_reader :calls
+
+ ##
+ # Creates a new batch request.
+ #
+ # @param [Hash] options
+ # Set of options for this request.
+ # @param [Proc] block
+ # Callback for every call's response. Won't be called if a call defined
+ # a callback of its own.
+ #
+ # @return [Legacy::Google::APIClient::BatchRequest]
+ # The constructed object.
+ #
+ # @yield [Legacy::Google::APIClient::Result]
+ # block to be called when result ready
+ def initialize(options = {}, &block)
+ @calls = []
+ @global_callback = nil
+ @global_callback = block if block_given?
+ @last_auto_id = 0
+
+ @base_id = SecureRandom.uuid
+
+ options[:uri] ||= 'https://www.googleapis.com/batch'
+ options[:http_method] ||= 'POST'
+
+ super options
+ end
+
+ ##
+ # Add a new call to the batch request.
+ # Each call must have its own call ID; if not provided, one will
+ # automatically be generated, avoiding collisions. If duplicate call IDs
+ # are provided, an error will be thrown.
+ #
+ # @param [Hash, Legacy::Google::APIClient::Request] call
+ # the call to be added.
+ # @param [String] call_id
+ # the ID to be used for this call. Must be unique
+ # @param [Proc] block
+ # callback for this call's response.
+ #
+ # @return [Legacy::Google::APIClient::BatchRequest]
+ # the BatchRequest, for chaining
+ #
+ # @yield [Legacy::Google::APIClient::Result]
+ # block to be called when result ready
+ def add(call, call_id = nil, &block)
+ unless call.kind_of?(Legacy::Google::APIClient::Reference)
+ call = Legacy::Google::APIClient::Reference.new(call)
+ end
+ call_id ||= new_id
+ if @calls.assoc(call_id)
+ raise BatchError,
+ 'A call with this ID already exists: %s' % call_id
+ end
+ callback = block_given? ? block : @global_callback
+ @calls << [call_id, call, callback]
+ return self
+ end
+
+ ##
+ # Processes the HTTP response to the batch request, issuing callbacks.
+ #
+ # @api private
+ #
+ # @param [Faraday::Response] response
+ # the HTTP response.
+ def process_http_response(response)
+ content_type = find_header('Content-Type', response.headers)
+ m = /.*boundary=(.+)/.match(content_type)
+ if m
+ boundary = m[1]
+ parts = response.body.split(/--#{Regexp.escape(boundary)}/)
+ parts = parts[1...-1]
+ parts.each do |part|
+ call_response = deserialize_call_response(part)
+ _, call, callback = @calls.assoc(call_response.call_id)
+ result = Legacy::Google::APIClient::Result.new(call, call_response)
+ callback.call(result) if callback
+ end
+ end
+ Legacy::Google::APIClient::Result.new(self, response)
+ end
+
+ ##
+ # Return the request body for the BatchRequest's HTTP request.
+ #
+ # @api private
+ #
+ # @return [String]
+ # the request body.
+ def to_http_request
+ if @calls.nil? || @calls.empty?
+ raise BatchError, 'Cannot make an empty batch request'
+ end
+ parts = @calls.map {|(call_id, call, _callback)| serialize_call(call_id, call)}
+ build_multipart(parts, 'multipart/mixed', BATCH_BOUNDARY)
+ super
+ end
+
+
+ protected
+
+ ##
+ # Helper method to find a header from its name, regardless of case.
+ #
+ # @api private
+ #
+ # @param [String] name
+ # the name of the header to find.
+ # @param [Hash] headers
+ # the hash of headers and their values.
+ #
+ # @return [String]
+ # the value of the desired header.
+ def find_header(name, headers)
+ _, header = headers.detect do |h, v|
+ h.downcase == name.downcase
+ end
+ return header
+ end
+
+ ##
+ # Create a new call ID. Uses an auto-incrementing, conflict-avoiding ID.
+ #
+ # @api private
+ #
+ # @return [String]
+ # the new, unique ID.
+ def new_id
+ @last_auto_id += 1
+ while @calls.assoc(@last_auto_id)
+ @last_auto_id += 1
+ end
+ return @last_auto_id.to_s
+ end
+
+ ##
+ # Convert a Content-ID header value to an id. Presumes the Content-ID
+ # header conforms to the format that id_to_header() returns.
+ #
+ # @api private
+ #
+ # @param [String] header
+ # Content-ID header value.
+ #
+ # @return [String]
+ # The extracted ID value.
+ def header_to_id(header)
+ if !header.start_with?('<') || !header.end_with?('>') ||
+ !header.include?('+')
+ raise BatchError, 'Invalid value for Content-ID: "%s"' % header
+ end
+
+ _base, call_id = header[1...-1].split('+')
+ return Addressable::URI.unencode(call_id)
+ end
+
+ ##
+ # Auxiliary method to split the headers from the body in an HTTP response.
+ #
+ # @api private
+ #
+ # @param [String] response
+ # the response to parse.
+ #
+ # @return [Array, String]
+ # the headers and the body, separately.
+ def split_headers_and_body(response)
+ headers = {}
+ payload = response.lstrip
+ while payload
+ line, payload = payload.split("\n", 2)
+ line.sub!(/\s+\z/, '')
+ break if line.empty?
+ match = /\A([^:]+):\s*/.match(line)
+ if match
+ headers[match[1]] = match.post_match
+ else
+ raise BatchError, 'Invalid header line in response: %s' % line
+ end
+ end
+ return headers, payload
+ end
+
+ ##
+ # Convert a single batched response into a BatchedCallResponse object.
+ #
+ # @api private
+ #
+ # @param [String] call_response
+ # the request to deserialize.
+ #
+ # @return [Legacy::Google::APIClient::BatchedCallResponse]
+ # the parsed and converted response.
+ def deserialize_call_response(call_response)
+ outer_headers, outer_body = split_headers_and_body(call_response)
+ status_line, payload = outer_body.split("\n", 2)
+ _protocol, status, _reason = status_line.split(' ', 3)
+
+ headers, body = split_headers_and_body(payload)
+ content_id = find_header('Content-ID', outer_headers)
+ call_id = header_to_id(content_id)
+ return BatchedCallResponse.new(call_id, status.to_i, headers, body)
+ end
+
+ ##
+ # Serialize a single batched call for assembling the multipart message
+ #
+ # @api private
+ #
+ # @param [Legacy::Google::APIClient::Request] call
+ # the call to serialize.
+ #
+ # @return [Faraday::UploadIO]
+ # the serialized request
+ def serialize_call(call_id, call)
+ method, uri, headers, body = call.to_http_request
+ request = "#{method.to_s.upcase} #{Addressable::URI.parse(uri).request_uri} HTTP/1.1"
+ headers.each do |header, value|
+ request << "\r\n%s: %s" % [header, value]
+ end
+ if body
+ # TODO - CompositeIO if body is a stream
+ request << "\r\n\r\n"
+ if body.respond_to?(:read)
+ request << body.read
+ else
+ request << body.to_s
+ end
+ end
+ Faraday::UploadIO.new(StringIO.new(request), 'application/http', 'ruby-api-request', 'Content-ID' => id_to_header(call_id))
+ end
+
+ ##
+ # Convert an id to a Content-ID header value.
+ #
+ # @api private
+ #
+ # @param [String] call_id
+ # identifier of individual call.
+ #
+ # @return [String]
+ # A Content-ID header with the call_id encoded into it. A UUID is
+ # prepended to the value because Content-ID headers are supposed to be
+ # universally unique.
+ def id_to_header(call_id)
+ return '<%s+%s>' % [@base_id, Addressable::URI.encode(call_id)]
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/charset.rb b/lib/legacy/google/api_client/charset.rb
new file mode 100644
index 00000000000..2ec2f2fae09
--- /dev/null
+++ b/lib/legacy/google/api_client/charset.rb
@@ -0,0 +1,35 @@
+require 'faraday'
+require 'zlib'
+
+module Legacy
+ module Google
+ class APIClient
+ class Charset < Faraday::Response::Middleware
+ include Legacy::Google::APIClient::Logging
+
+ def charset_for_content_type(type)
+ if type
+ m = type.match(/(?:charset|encoding)="?([a-z0-9-]+)"?/i)
+ if m
+ return Encoding.find(m[1])
+ end
+ end
+ nil
+ end
+
+ def adjust_encoding(env)
+ charset = charset_for_content_type(env[:response_headers]['content-type'])
+ if charset && env[:body].encoding != charset
+ env[:body].force_encoding(charset)
+ end
+ end
+
+ def on_complete(env)
+ adjust_encoding(env)
+ end
+ end
+ end
+ end
+end
+
+Faraday::Response.register_middleware :charset => Legacy::Google::APIClient::Charset
diff --git a/lib/legacy/google/api_client/client_secrets.rb b/lib/legacy/google/api_client/client_secrets.rb
new file mode 100644
index 00000000000..bc424d5cb2e
--- /dev/null
+++ b/lib/legacy/google/api_client/client_secrets.rb
@@ -0,0 +1,180 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+require 'compat/multi_json'
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # Manages the persistence of client configuration data and secrets. Format
+ # inspired by the Google API Python client.
+ #
+ # @see https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
+ #
+ # @example
+ # {
+ # "web": {
+ # "client_id": "asdfjasdljfasdkjf",
+ # "client_secret": "1912308409123890",
+ # "redirect_uris": ["https://www.example.com/oauth2callback"],
+ # "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+ # "token_uri": "https://accounts.google.com/o/oauth2/token"
+ # }
+ # }
+ #
+ # @example
+ # {
+ # "installed": {
+ # "client_id": "837647042410-75ifg...usercontent.com",
+ # "client_secret":"asdlkfjaskd",
+ # "redirect_uris": ["http://localhost", "urn:ietf:oauth:2.0:oob"],
+ # "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+ # "token_uri": "https://accounts.google.com/o/oauth2/token"
+ # }
+ # }
+ class ClientSecrets
+
+ ##
+ # Reads client configuration from a file
+ #
+ # @param [String] filename
+ # Path to file to load
+ #
+ # @return [Legacy::Google::APIClient::ClientSecrets]
+ # OAuth client settings
+ def self.load(filename=nil)
+ if filename && File.directory?(filename)
+ search_path = File.expand_path(filename)
+ filename = nil
+ end
+ while filename == nil
+ search_path ||= File.expand_path('.')
+ if File.exists?(File.join(search_path, 'client_secrets.json'))
+ filename = File.join(search_path, 'client_secrets.json')
+ elsif search_path == '/' || search_path =~ /[a-zA-Z]:[\/\\]/
+ raise ArgumentError,
+ 'No client_secrets.json filename supplied ' +
+ 'and/or could not be found in search path.'
+ else
+ search_path = File.expand_path(File.join(search_path, '..'))
+ end
+ end
+ data = File.open(filename, 'r') { |file| MultiJson.load(file.read) }
+ return self.new(data)
+ end
+
+ ##
+ # Intialize OAuth client settings.
+ #
+ # @param [Hash] options
+ # Parsed client secrets files
+ def initialize(options={})
+ # Client auth configuration
+ @flow = options[:flow] || options.keys.first.to_s || 'web'
+ fdata = options[@flow]
+ @client_id = fdata[:client_id] || fdata["client_id"]
+ @client_secret = fdata[:client_secret] || fdata["client_secret"]
+ @redirect_uris = fdata[:redirect_uris] || fdata["redirect_uris"]
+ @redirect_uris ||= [fdata[:redirect_uri] || fdata["redirect_uri"]].compact
+ @javascript_origins = (
+ fdata[:javascript_origins] ||
+ fdata["javascript_origins"]
+ )
+ @javascript_origins ||= [fdata[:javascript_origin] || fdata["javascript_origin"]].compact
+ @authorization_uri = fdata[:auth_uri] || fdata["auth_uri"]
+ @authorization_uri ||= fdata[:authorization_uri]
+ @token_credential_uri = fdata[:token_uri] || fdata["token_uri"]
+ @token_credential_uri ||= fdata[:token_credential_uri]
+
+ # Associated token info
+ @access_token = fdata[:access_token] || fdata["access_token"]
+ @refresh_token = fdata[:refresh_token] || fdata["refresh_token"]
+ @id_token = fdata[:id_token] || fdata["id_token"]
+ @expires_in = fdata[:expires_in] || fdata["expires_in"]
+ @expires_at = fdata[:expires_at] || fdata["expires_at"]
+ @issued_at = fdata[:issued_at] || fdata["issued_at"]
+ end
+
+ attr_reader(
+ :flow, :client_id, :client_secret, :redirect_uris, :javascript_origins,
+ :authorization_uri, :token_credential_uri, :access_token,
+ :refresh_token, :id_token, :expires_in, :expires_at, :issued_at
+ )
+
+ ##
+ # Serialize back to the original JSON form
+ #
+ # @return [String]
+ # JSON
+ def to_json
+ return MultiJson.dump(to_hash)
+ end
+
+ def to_hash
+ {
+ self.flow => ({
+ 'client_id' => self.client_id,
+ 'client_secret' => self.client_secret,
+ 'redirect_uris' => self.redirect_uris,
+ 'javascript_origins' => self.javascript_origins,
+ 'auth_uri' => self.authorization_uri,
+ 'token_uri' => self.token_credential_uri,
+ 'access_token' => self.access_token,
+ 'refresh_token' => self.refresh_token,
+ 'id_token' => self.id_token,
+ 'expires_in' => self.expires_in,
+ 'expires_at' => self.expires_at,
+ 'issued_at' => self.issued_at
+ }).inject({}) do |accu, (k, v)|
+ # Prunes empty values from JSON output.
+ unless v == nil || (v.respond_to?(:empty?) && v.empty?)
+ accu[k] = v
+ end
+ accu
+ end
+ }
+ end
+
+ def to_authorization
+ gem 'signet', '>= 0.4.0'
+ require 'signet/oauth_2/client'
+ # NOTE: Do not rely on this default value, as it may change
+ new_authorization = Signet::OAuth2::Client.new
+ new_authorization.client_id = self.client_id
+ new_authorization.client_secret = self.client_secret
+ new_authorization.authorization_uri = (
+ self.authorization_uri ||
+ 'https://accounts.google.com/o/oauth2/auth'
+ )
+ new_authorization.token_credential_uri = (
+ self.token_credential_uri ||
+ 'https://accounts.google.com/o/oauth2/token'
+ )
+ new_authorization.redirect_uri = self.redirect_uris.first
+
+ # These are supported, but unlikely.
+ new_authorization.access_token = self.access_token
+ new_authorization.refresh_token = self.refresh_token
+ new_authorization.id_token = self.id_token
+ new_authorization.expires_in = self.expires_in
+ new_authorization.issued_at = self.issued_at if self.issued_at
+ new_authorization.expires_at = self.expires_at if self.expires_at
+ return new_authorization
+ end
+ end
+ end
+ end
+end
diff --git a/lib/google/api_client/discovery.rb b/lib/legacy/google/api_client/discovery.rb
similarity index 73%
rename from lib/google/api_client/discovery.rb
rename to lib/legacy/google/api_client/discovery.rb
index bb01d67ce76..59a5d56dd69 100644
--- a/lib/google/api_client/discovery.rb
+++ b/lib/legacy/google/api_client/discovery.rb
@@ -13,7 +13,7 @@
# limitations under the License.
-require 'google/api_client/discovery/api'
-require 'google/api_client/discovery/resource'
-require 'google/api_client/discovery/method'
-require 'google/api_client/discovery/schema'
+require 'legacy/google/api_client/discovery/api'
+require 'legacy/google/api_client/discovery/resource'
+require 'legacy/google/api_client/discovery/method'
+require 'legacy/google/api_client/discovery/schema'
diff --git a/lib/legacy/google/api_client/discovery/api.rb b/lib/legacy/google/api_client/discovery/api.rb
new file mode 100644
index 00000000000..ab2a49653a5
--- /dev/null
+++ b/lib/legacy/google/api_client/discovery/api.rb
@@ -0,0 +1,312 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+require 'addressable/uri'
+require 'multi_json'
+require 'active_support/inflector'
+require 'legacy/google/api_client/discovery/resource'
+require 'legacy/google/api_client/discovery/method'
+require 'legacy/google/api_client/discovery/media'
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # A service that has been described by a discovery document.
+ class API
+
+ ##
+ # Creates a description of a particular version of a service.
+ #
+ # @param [String] document_base
+ # Base URI for the discovery document.
+ # @param [Hash] discovery_document
+ # The section of the discovery document that applies to this service
+ # version.
+ #
+ # @return [Legacy::Google::APIClient::API] The constructed service object.
+ def initialize(document_base, discovery_document)
+ @document_base = Addressable::URI.parse(document_base)
+ @discovery_document = discovery_document
+ metaclass = (class << self; self; end)
+ self.discovered_resources.each do |resource|
+ method_name = ActiveSupport::Inflector.underscore(resource.name).to_sym
+ if !self.respond_to?(method_name)
+ metaclass.send(:define_method, method_name) { resource }
+ end
+ end
+ self.discovered_methods.each do |method|
+ method_name = ActiveSupport::Inflector.underscore(method.name).to_sym
+ if !self.respond_to?(method_name)
+ metaclass.send(:define_method, method_name) { method }
+ end
+ end
+ end
+
+ # @return [String] unparsed discovery document for the API
+ attr_reader :discovery_document
+
+ ##
+ # Returns the id of the service.
+ #
+ # @return [String] The service id.
+ def id
+ return (
+ @discovery_document['id'] ||
+ "#{self.name}:#{self.version}"
+ )
+ end
+
+ ##
+ # Returns the identifier for the service.
+ #
+ # @return [String] The service identifier.
+ def name
+ return @discovery_document['name']
+ end
+
+ ##
+ # Returns the version of the service.
+ #
+ # @return [String] The service version.
+ def version
+ return @discovery_document['version']
+ end
+
+ ##
+ # Returns a human-readable title for the API.
+ #
+ # @return [Hash] The API title.
+ def title
+ return @discovery_document['title']
+ end
+
+ ##
+ # Returns a human-readable description of the API.
+ #
+ # @return [Hash] The API description.
+ def description
+ return @discovery_document['description']
+ end
+
+ ##
+ # Returns a URI for the API documentation.
+ #
+ # @return [Hash] The API documentation.
+ def documentation
+ return Addressable::URI.parse(@discovery_document['documentationLink'])
+ end
+
+ ##
+ # Returns true if this is the preferred version of this API.
+ #
+ # @return [TrueClass, FalseClass]
+ # Whether or not this is the preferred version of this API.
+ def preferred
+ return !!@discovery_document['preferred']
+ end
+
+ ##
+ # Returns the list of API features.
+ #
+ # @return [Array]
+ # The features supported by this API.
+ def features
+ return @discovery_document['features'] || []
+ end
+
+ ##
+ # Returns the root URI for this service.
+ #
+ # @return [Addressable::URI] The root URI.
+ def root_uri
+ return @root_uri ||= (
+ Addressable::URI.parse(self.discovery_document['rootUrl'])
+ )
+ end
+
+ ##
+ # Returns true if this API uses a data wrapper.
+ #
+ # @return [TrueClass, FalseClass]
+ # Whether or not this API uses a data wrapper.
+ def data_wrapper?
+ return self.features.include?('dataWrapper')
+ end
+
+ ##
+ # Returns the base URI for the discovery document.
+ #
+ # @return [Addressable::URI] The base URI.
+ attr_reader :document_base
+
+ ##
+ # Returns the base URI for this version of the service.
+ #
+ # @return [Addressable::URI] The base URI that methods are joined to.
+ def method_base
+ if @discovery_document['basePath']
+ return @method_base ||= (
+ self.root_uri.join(Addressable::URI.parse(@discovery_document['basePath']))
+ ).normalize
+ else
+ return nil
+ end
+ end
+
+ ##
+ # Updates the hierarchy of resources and methods with the new base.
+ #
+ # @param [Addressable::URI, #to_str, String] new_method_base
+ # The new base URI to use for the service.
+ def method_base=(new_method_base)
+ @method_base = Addressable::URI.parse(new_method_base)
+ self.discovered_resources.each do |resource|
+ resource.method_base = @method_base
+ end
+ self.discovered_methods.each do |method|
+ method.method_base = @method_base
+ end
+ end
+
+ ##
+ # Returns the base URI for batch calls to this service.
+ #
+ # @return [Addressable::URI] The base URI that methods are joined to.
+ def batch_path
+ if @discovery_document['batchPath']
+ return @batch_path ||= (
+ self.document_base.join(Addressable::URI.parse('/' +
+ @discovery_document['batchPath']))
+ ).normalize
+ else
+ return nil
+ end
+ end
+
+ ##
+ # A list of schemas available for this version of the API.
+ #
+ # @return [Hash] A list of {Legacy::Google::APIClient::Schema} objects.
+ def schemas
+ return @schemas ||= (
+ (@discovery_document['schemas'] || []).inject({}) do |accu, (k, v)|
+ accu[k] = Legacy::Google::APIClient::Schema.parse(self, v)
+ accu
+ end
+ )
+ end
+
+ ##
+ # Returns a schema for a kind value.
+ #
+ # @return [Legacy::Google::APIClient::Schema] The associated Schema object.
+ def schema_for_kind(kind)
+ api_name, schema_name = kind.split('#', 2)
+ if api_name != self.name
+ raise ArgumentError,
+ "The kind does not match this API. " +
+ "Expected '#{self.name}', got '#{api_name}'."
+ end
+ for k, v in self.schemas
+ return v if k.downcase == schema_name.downcase
+ end
+ return nil
+ end
+
+ ##
+ # A list of resources available at the root level of this version of the
+ # API.
+ #
+ # @return [Array] A list of {Legacy::Google::APIClient::Resource} objects.
+ def discovered_resources
+ return @discovered_resources ||= (
+ (@discovery_document['resources'] || []).inject([]) do |accu, (k, v)|
+ accu << Legacy::Google::APIClient::Resource.new(
+ self, self.method_base, k, v
+ )
+ accu
+ end
+ )
+ end
+
+ ##
+ # A list of methods available at the root level of this version of the
+ # API.
+ #
+ # @return [Array] A list of {Legacy::Google::APIClient::Method} objects.
+ def discovered_methods
+ return @discovered_methods ||= (
+ (@discovery_document['methods'] || []).inject([]) do |accu, (k, v)|
+ accu << Legacy::Google::APIClient::Method.new(self, self.method_base, k, v)
+ accu
+ end
+ )
+ end
+
+ ##
+ # Allows deep inspection of the discovery document.
+ def [](key)
+ return @discovery_document[key]
+ end
+
+ ##
+ # Converts the service to a flat mapping of RPC names and method objects.
+ #
+ # @return [Hash] All methods available on the service.
+ #
+ # @example
+ # # Discover available methods
+ # method_names = client.discovered_api('buzz').to_h.keys
+ def to_h
+ return @hash ||= (begin
+ methods_hash = {}
+ self.discovered_methods.each do |method|
+ methods_hash[method.id] = method
+ end
+ self.discovered_resources.each do |resource|
+ methods_hash.merge!(resource.to_h)
+ end
+ methods_hash
+ end)
+ end
+
+ ##
+ # Returns a String representation of the service's state.
+ #
+ # @return [String] The service's state, as a String.
+ def inspect
+ sprintf(
+ "#<%s:%#0x ID:%s>", self.class.to_s, self.object_id, self.id
+ )
+ end
+
+ ##
+ # Marshalling support - serialize the API to a string (doc base + original
+ # discovery document).
+ def _dump(level)
+ MultiJson.dump([@document_base.to_s, @discovery_document])
+ end
+
+ ##
+ # Marshalling support - Restore an API instance from serialized form
+ def self._load(obj)
+ new(*MultiJson.load(obj))
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/discovery/media.rb b/lib/legacy/google/api_client/discovery/media.rb
new file mode 100644
index 00000000000..c5db92e6eae
--- /dev/null
+++ b/lib/legacy/google/api_client/discovery/media.rb
@@ -0,0 +1,78 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+require 'addressable/uri'
+require 'addressable/template'
+
+require 'legacy/google/api_client/errors'
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # Media upload elements for discovered methods
+ class MediaUpload
+
+ ##
+ # Creates a description of a particular method.
+ #
+ # @param [Legacy::Google::APIClient::API] api
+ # Base discovery document for the API
+ # @param [Addressable::URI] method_base
+ # The base URI for the service.
+ # @param [Hash] discovery_document
+ # The media upload section of the discovery document.
+ #
+ # @return [Legacy::Google::APIClient::Method] The constructed method object.
+ def initialize(api, method_base, discovery_document)
+ @api = api
+ @method_base = method_base
+ @discovery_document = discovery_document
+ end
+
+ ##
+ # List of acceptable mime types
+ #
+ # @return [Array]
+ # List of acceptable mime types for uploaded content
+ def accepted_types
+ @discovery_document['accept']
+ end
+
+ ##
+ # Maximum size of an uplad
+ # TODO: Parse & convert to numeric value
+ #
+ # @return [String]
+ def max_size
+ @discovery_document['maxSize']
+ end
+
+ ##
+ # Returns the URI template for the method. A parameter list can be
+ # used to expand this into a URI.
+ #
+ # @return [Addressable::Template] The URI template.
+ def uri_template
+ return @uri_template ||= Addressable::Template.new(
+ @api.method_base.join(Addressable::URI.parse(@discovery_document['protocols']['simple']['path']))
+ )
+ end
+
+ end
+
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/discovery/method.rb b/lib/legacy/google/api_client/discovery/method.rb
new file mode 100644
index 00000000000..060a25dd3ef
--- /dev/null
+++ b/lib/legacy/google/api_client/discovery/method.rb
@@ -0,0 +1,364 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+require 'addressable/uri'
+require 'addressable/template'
+
+require 'legacy/google/api_client/errors'
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # A method that has been described by a discovery document.
+ class Method
+
+ ##
+ # Creates a description of a particular method.
+ #
+ # @param [Legacy::Google::APIClient::API] api
+ # The API this method belongs to.
+ # @param [Addressable::URI] method_base
+ # The base URI for the service.
+ # @param [String] method_name
+ # The identifier for the method.
+ # @param [Hash] discovery_document
+ # The section of the discovery document that applies to this method.
+ #
+ # @return [Legacy::Google::APIClient::Method] The constructed method object.
+ def initialize(api, method_base, method_name, discovery_document)
+ @api = api
+ @method_base = method_base
+ @name = method_name
+ @discovery_document = discovery_document
+ end
+
+ # @return [String] unparsed discovery document for the method
+ attr_reader :discovery_document
+
+ ##
+ # Returns the API this method belongs to.
+ #
+ # @return [Legacy::Google::APIClient::API] The API this method belongs to.
+ attr_reader :api
+
+ ##
+ # Returns the identifier for the method.
+ #
+ # @return [String] The method identifier.
+ attr_reader :name
+
+ ##
+ # Returns the base URI for the method.
+ #
+ # @return [Addressable::URI]
+ # The base URI that this method will be joined to.
+ attr_reader :method_base
+
+ ##
+ # Updates the method with the new base.
+ #
+ # @param [Addressable::URI, #to_str, String] new_method_base
+ # The new base URI to use for the method.
+ def method_base=(new_method_base)
+ @method_base = Addressable::URI.parse(new_method_base)
+ @uri_template = nil
+ end
+
+ ##
+ # Returns a human-readable description of the method.
+ #
+ # @return [Hash] The API description.
+ def description
+ return @discovery_document['description']
+ end
+
+ ##
+ # Returns the method ID.
+ #
+ # @return [String] The method identifier.
+ def id
+ return @discovery_document['id']
+ end
+
+ ##
+ # Returns the HTTP method or 'GET' if none is specified.
+ #
+ # @return [String] The HTTP method that will be used in the request.
+ def http_method
+ return @discovery_document['httpMethod'] || 'GET'
+ end
+
+ ##
+ # Returns the URI template for the method. A parameter list can be
+ # used to expand this into a URI.
+ #
+ # @return [Addressable::Template] The URI template.
+ def uri_template
+ return @uri_template ||= Addressable::Template.new(
+ self.method_base.join(Addressable::URI.parse("./" + @discovery_document['path']))
+ )
+ end
+
+ ##
+ # Returns media upload information for this method, if supported
+ #
+ # @return [Legacy::Google::APIClient::MediaUpload] Description of upload endpoints
+ def media_upload
+ if @discovery_document['mediaUpload']
+ return @media_upload ||= Legacy::Google::APIClient::MediaUpload.new(self, self.method_base, @discovery_document['mediaUpload'])
+ else
+ return nil
+ end
+ end
+
+ ##
+ # Returns the Schema object for the method's request, if any.
+ #
+ # @return [Legacy::Google::APIClient::Schema] The request schema.
+ def request_schema
+ if @discovery_document['request']
+ schema_name = @discovery_document['request']['$ref']
+ return @api.schemas[schema_name]
+ else
+ return nil
+ end
+ end
+
+ ##
+ # Returns the Schema object for the method's response, if any.
+ #
+ # @return [Legacy::Google::APIClient::Schema] The response schema.
+ def response_schema
+ if @discovery_document['response']
+ schema_name = @discovery_document['response']['$ref']
+ return @api.schemas[schema_name]
+ else
+ return nil
+ end
+ end
+
+ ##
+ # Normalizes parameters, converting to the appropriate types.
+ #
+ # @param [Hash, Array] parameters
+ # The parameters to normalize.
+ #
+ # @return [Hash] The normalized parameters.
+ def normalize_parameters(parameters={})
+ # Convert keys to Strings when appropriate
+ if parameters.kind_of?(Hash) || parameters.kind_of?(Array)
+ # Returning an array since parameters can be repeated (ie, Adsense Management API)
+ parameters = parameters.inject([]) do |accu, (k, v)|
+ k = k.to_s if k.kind_of?(Symbol)
+ k = k.to_str if k.respond_to?(:to_str)
+ unless k.kind_of?(String)
+ raise TypeError, "Expected String, got #{k.class}."
+ end
+ accu << [k, v]
+ accu
+ end
+ else
+ raise TypeError,
+ "Expected Hash or Array, got #{parameters.class}."
+ end
+ return parameters
+ end
+
+ ##
+ # Expands the method's URI template using a parameter list.
+ #
+ # @api private
+ # @param [Hash, Array] parameters
+ # The parameter list to use.
+ #
+ # @return [Addressable::URI] The URI after expansion.
+ def generate_uri(parameters={})
+ parameters = self.normalize_parameters(parameters)
+
+ self.validate_parameters(parameters)
+ template_variables = self.uri_template.variables
+ upload_type = parameters.assoc('uploadType') || parameters.assoc('upload_type')
+ if upload_type
+ unless self.media_upload
+ raise ArgumentException, "Media upload not supported for this method"
+ end
+ case upload_type.last
+ when 'media', 'multipart', 'resumable'
+ uri = self.media_upload.uri_template.expand(parameters)
+ else
+ raise ArgumentException, "Invalid uploadType '#{upload_type}'"
+ end
+ else
+ uri = self.uri_template.expand(parameters)
+ end
+ query_parameters = parameters.reject do |k, v|
+ template_variables.include?(k)
+ end
+ # encode all non-template parameters
+ params = ""
+ unless query_parameters.empty?
+ params = "?" + Addressable::URI.form_encode(query_parameters.sort)
+ end
+ # Normalization is necessary because of undesirable percent-escaping
+ # during URI template expansion
+ return uri.normalize + params
+ end
+
+ ##
+ # Generates an HTTP request for this method.
+ #
+ # @api private
+ # @param [Hash, Array] parameters
+ # The parameters to send.
+ # @param [String, StringIO] body The body for the HTTP request.
+ # @param [Hash, Array] headers The HTTP headers for the request.
+ # @option options [Faraday::Connection] :connection
+ # The HTTP connection to use.
+ #
+ # @return [Array] The generated HTTP request.
+ def generate_request(parameters={}, body='', headers={}, options={})
+ if !headers.kind_of?(Array) && !headers.kind_of?(Hash)
+ raise TypeError, "Expected Hash or Array, got #{headers.class}."
+ end
+ method = self.http_method.to_s.downcase.to_sym
+ uri = self.generate_uri(parameters)
+ headers = Faraday::Utils::Headers.new(headers)
+ return [method, uri, headers, body]
+ end
+
+
+ ##
+ # Returns a Hash of the parameter descriptions for
+ # this method.
+ #
+ # @return [Hash] The parameter descriptions.
+ def parameter_descriptions
+ @parameter_descriptions ||= (
+ @discovery_document['parameters'] || {}
+ ).inject({}) { |h,(k,v)| h[k]=v; h }
+ end
+
+ ##
+ # Returns an Array of the parameters for this method.
+ #
+ # @return [Array] The parameters.
+ def parameters
+ @parameters ||= ((
+ @discovery_document['parameters'] || {}
+ ).inject({}) { |h,(k,v)| h[k]=v; h }).keys
+ end
+
+ ##
+ # Returns an Array of the required parameters for this
+ # method.
+ #
+ # @return [Array] The required parameters.
+ #
+ # @example
+ # # A list of all required parameters.
+ # method.required_parameters
+ def required_parameters
+ @required_parameters ||= ((self.parameter_descriptions.select do |k, v|
+ v['required']
+ end).inject({}) { |h,(k,v)| h[k]=v; h }).keys
+ end
+
+ ##
+ # Returns an Array of the optional parameters for this
+ # method.
+ #
+ # @return [Array] The optional parameters.
+ #
+ # @example
+ # # A list of all optional parameters.
+ # method.optional_parameters
+ def optional_parameters
+ @optional_parameters ||= ((self.parameter_descriptions.reject do |k, v|
+ v['required']
+ end).inject({}) { |h,(k,v)| h[k]=v; h }).keys
+ end
+
+ ##
+ # Verifies that the parameters are valid for this method. Raises an
+ # exception if validation fails.
+ #
+ # @api private
+ # @param [Hash, Array] parameters
+ # The parameters to verify.
+ #
+ # @return [NilClass] nil if validation passes.
+ def validate_parameters(parameters={})
+ parameters = self.normalize_parameters(parameters)
+ required_variables = ((self.parameter_descriptions.select do |k, v|
+ v['required']
+ end).inject({}) { |h,(k,v)| h[k]=v; h }).keys
+ missing_variables = required_variables - parameters.map { |(k, _)| k }
+ if missing_variables.size > 0
+ raise ArgumentError,
+ "Missing required parameters: #{missing_variables.join(', ')}."
+ end
+ parameters.each do |k, v|
+ # Handle repeated parameters.
+ if self.parameter_descriptions[k] &&
+ self.parameter_descriptions[k]['repeated'] &&
+ v.kind_of?(Array)
+ # If this is a repeated parameter and we've got an array as a
+ # value, just provide the whole array to the loop below.
+ items = v
+ else
+ # If this is not a repeated parameter, or if it is but we're
+ # being given a single value, wrap the value in an array, so that
+ # the loop below still works for the single element.
+ items = [v]
+ end
+
+ items.each do |item|
+ if self.parameter_descriptions[k]
+ enum = self.parameter_descriptions[k]['enum']
+ if enum && !enum.include?(item)
+ raise ArgumentError,
+ "Parameter '#{k}' has an invalid value: #{item}. " +
+ "Must be one of #{enum.inspect}."
+ end
+ pattern = self.parameter_descriptions[k]['pattern']
+ if pattern
+ regexp = Regexp.new("^#{pattern}$")
+ if item !~ regexp
+ raise ArgumentError,
+ "Parameter '#{k}' has an invalid value: #{item}. " +
+ "Must match: /^#{pattern}$/."
+ end
+ end
+ end
+ end
+ end
+ return nil
+ end
+
+ ##
+ # Returns a String representation of the method's state.
+ #
+ # @return [String] The method's state, as a String.
+ def inspect
+ sprintf(
+ "#<%s:%#0x ID:%s>",
+ self.class.to_s, self.object_id, self.id
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/discovery/resource.rb b/lib/legacy/google/api_client/discovery/resource.rb
new file mode 100644
index 00000000000..71ca9595cbe
--- /dev/null
+++ b/lib/legacy/google/api_client/discovery/resource.rb
@@ -0,0 +1,157 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+require 'addressable/uri'
+
+require 'active_support/inflector'
+require 'legacy/google/api_client/discovery/method'
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # A resource that has been described by a discovery document.
+ class Resource
+
+ ##
+ # Creates a description of a particular version of a resource.
+ #
+ # @param [Legacy::Google::APIClient::API] api
+ # The API this resource belongs to.
+ # @param [Addressable::URI] method_base
+ # The base URI for the service.
+ # @param [String] resource_name
+ # The identifier for the resource.
+ # @param [Hash] discovery_document
+ # The section of the discovery document that applies to this resource.
+ #
+ # @return [Legacy::Google::APIClient::Resource] The constructed resource object.
+ def initialize(api, method_base, resource_name, discovery_document)
+ @api = api
+ @method_base = method_base
+ @name = resource_name
+ @discovery_document = discovery_document
+ metaclass = (class <String representation of the resource's state.
+ #
+ # @return [String] The resource's state, as a String.
+ def inspect
+ sprintf(
+ "#<%s:%#0x NAME:%s>", self.class.to_s, self.object_id, self.name
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/discovery/schema.rb b/lib/legacy/google/api_client/discovery/schema.rb
new file mode 100644
index 00000000000..9f2c2ee864d
--- /dev/null
+++ b/lib/legacy/google/api_client/discovery/schema.rb
@@ -0,0 +1,118 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+require 'time'
+require 'multi_json'
+require 'compat/multi_json'
+require 'base64'
+require 'autoparse'
+require 'addressable/uri'
+require 'addressable/template'
+
+require 'active_support/inflector'
+require 'legacy/google/api_client/errors'
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # @api private
+ module Schema
+ def self.parse(api, schema_data)
+ # This method is super-long, but hard to break up due to the
+ # unavoidable dependence on closures and execution context.
+ schema_name = schema_data['id']
+
+ # Due to an oversight, schema IDs may not be URI references.
+ # TODO(bobaman): Remove this code once this has been resolved.
+ schema_uri = (
+ api.document_base +
+ (schema_name[0..0] != '#' ? '#' + schema_name : schema_name)
+ )
+
+ # Due to an oversight, schema IDs may not be URI references.
+ # TODO(bobaman): Remove this whole lambda once this has been resolved.
+ reformat_references = lambda do |data|
+ # This code is not particularly efficient due to recursive traversal
+ # and excess object creation, but this hopefully shouldn't be an
+ # issue since it should only be called only once per schema per
+ # process.
+ if data.kind_of?(Hash) &&
+ data['$ref'] && !data['$ref'].kind_of?(Hash)
+ if data['$ref'].respond_to?(:to_str)
+ reference = data['$ref'].to_str
+ else
+ raise TypeError, "Expected String, got #{data['$ref'].class}"
+ end
+ reference = '#' + reference if reference[0..0] != '#'
+ data.merge({
+ '$ref' => reference
+ })
+ elsif data.kind_of?(Hash)
+ data.inject({}) do |accu, (key, value)|
+ if value.kind_of?(Hash)
+ accu[key] = reformat_references.call(value)
+ else
+ accu[key] = value
+ end
+ accu
+ end
+ else
+ data
+ end
+ end
+ schema_data = reformat_references.call(schema_data)
+
+ if schema_name
+ api_name_string = ActiveSupport::Inflector.camelize(api.name)
+ api_version_string = ActiveSupport::Inflector.camelize(api.version).gsub('.', '_')
+ # This is for compatibility with Ruby 1.8.7.
+ # TODO(bobaman) Remove this when we eventually stop supporting 1.8.7.
+ args = []
+ args << false if Class.method(:const_defined?).arity != 1
+ if Legacy::Google::APIClient::Schema.const_defined?(api_name_string, *args)
+ api_name = Legacy::Google::APIClient::Schema.const_get(
+ api_name_string, *args
+ )
+ else
+ api_name = Legacy::Google::APIClient::Schema.const_set(
+ api_name_string, Module.new
+ )
+ end
+ if api_name.const_defined?(api_version_string, *args)
+ api_version = api_name.const_get(api_version_string, *args)
+ else
+ api_version = api_name.const_set(api_version_string, Module.new)
+ end
+ if api_version.const_defined?(schema_name, *args)
+ schema_class = api_version.const_get(schema_name, *args)
+ end
+ end
+
+ # It's possible the schema has already been defined. If so, don't
+ # redefine it. This means that reloading a schema which has already
+ # been loaded into memory is not possible.
+ unless schema_class
+ schema_class = AutoParse.generate(schema_data, :uri => schema_uri)
+ if schema_name
+ api_version.const_set(schema_name, schema_class)
+ end
+ end
+ return schema_class
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/environment.rb b/lib/legacy/google/api_client/environment.rb
new file mode 100644
index 00000000000..cc0931c4bba
--- /dev/null
+++ b/lib/legacy/google/api_client/environment.rb
@@ -0,0 +1,43 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Legacy
+ module Google
+ class APIClient
+ module ENV
+ OS_VERSION = begin
+ if RUBY_PLATFORM =~ /mswin|win32|mingw|bccwin|cygwin/
+ # TODO(bobaman)
+ # Confirm that all of these Windows environments actually have access
+ # to the `ver` command.
+ `ver`.sub(/\s*\[Version\s*/, '/').sub(']', '')
+ elsif RUBY_PLATFORM =~ /darwin/i
+ "Mac OS X/#{`sw_vers -productVersion`}"
+ elsif RUBY_PLATFORM == 'java'
+ # Get the information from java system properties to avoid spawning a
+ # sub-process, which is not friendly in some contexts (web servers).
+ require 'java'
+ name = java.lang.System.getProperty('os.name')
+ version = java.lang.System.getProperty('os.version')
+ "#{name}/#{version}"
+ else
+ `uname -sr`.sub(' ', '/')
+ end
+ rescue Exception
+ RUBY_PLATFORM
+ end.strip
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/errors.rb b/lib/legacy/google/api_client/errors.rb
new file mode 100644
index 00000000000..45f7f14ec2c
--- /dev/null
+++ b/lib/legacy/google/api_client/errors.rb
@@ -0,0 +1,66 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # An error which is raised when there is an unexpected response or other
+ # transport error that prevents an operation from succeeding.
+ class TransmissionError < StandardError
+ attr_reader :result
+ def initialize(message = nil, result = nil)
+ super(message)
+ @result = result
+ end
+ end
+
+ ##
+ # An exception that is raised if a redirect is required
+ #
+ class RedirectError < TransmissionError
+ end
+
+ ##
+ # An exception that is raised if a method is called with missing or
+ # invalid parameter values.
+ class ValidationError < StandardError
+ end
+
+ ##
+ # A 4xx class HTTP error occurred.
+ class ClientError < TransmissionError
+ end
+
+ ##
+ # A 401 HTTP error occurred.
+ class AuthorizationError < ClientError
+ end
+
+ ##
+ # A 5xx class HTTP error occurred.
+ class ServerError < TransmissionError
+ end
+
+ ##
+ # An exception that is raised if an ID token could not be validated.
+ class InvalidIDTokenError < StandardError
+ end
+
+ # Error class for problems in batch requests.
+ class BatchError < StandardError
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/gzip.rb b/lib/legacy/google/api_client/gzip.rb
new file mode 100644
index 00000000000..9cab8e22a08
--- /dev/null
+++ b/lib/legacy/google/api_client/gzip.rb
@@ -0,0 +1,30 @@
+require 'faraday'
+require 'zlib'
+
+module Legacy
+ module Google
+ class APIClient
+ class Gzip < Faraday::Response::Middleware
+ include Legacy::Google::APIClient::Logging
+
+ def on_complete(env)
+ encoding = env[:response_headers]['content-encoding'].to_s.downcase
+ case encoding
+ when 'gzip'
+ logger.debug { "Decompressing gzip encoded response (#{env[:body].length} bytes)" }
+ env[:body] = Zlib::GzipReader.new(StringIO.new(env[:body])).read
+ env[:response_headers].delete('content-encoding')
+ logger.debug { "Decompressed (#{env[:body].length} bytes)" }
+ when 'deflate'
+ logger.debug{ "Decompressing deflate encoded response (#{env[:body].length} bytes)" }
+ env[:body] = Zlib::Inflate.inflate(env[:body])
+ env[:response_headers].delete('content-encoding')
+ logger.debug { "Decompressed (#{env[:body].length} bytes)" }
+ end
+ end
+ end
+ end
+ end
+end
+
+Faraday::Response.register_middleware :gzip => Legacy::Google::APIClient::Gzip
diff --git a/lib/legacy/google/api_client/logging.rb b/lib/legacy/google/api_client/logging.rb
new file mode 100644
index 00000000000..d449cd09973
--- /dev/null
+++ b/lib/legacy/google/api_client/logging.rb
@@ -0,0 +1,34 @@
+require 'logger'
+
+module Legacy
+ module Google
+ class APIClient
+
+ class << self
+ ##
+ # Logger for the API client
+ #
+ # @return [Logger] logger instance.
+ attr_accessor :logger
+ end
+
+ self.logger = Logger.new(STDOUT)
+ self.logger.level = Logger::WARN
+
+ ##
+ # Module to make accessing the logger simpler
+ module Logging
+ ##
+ # Logger for the API client
+ #
+ # @return [Logger] logger instance.
+ def logger
+ Legacy::Google::APIClient.logger
+ end
+ end
+
+ end
+
+
+ end
+end
diff --git a/lib/legacy/google/api_client/media.rb b/lib/legacy/google/api_client/media.rb
new file mode 100644
index 00000000000..9ae31d8b45f
--- /dev/null
+++ b/lib/legacy/google/api_client/media.rb
@@ -0,0 +1,261 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+require 'legacy/google/api_client/reference'
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # Uploadable media support. Holds an IO stream & content type.
+ #
+ # @see Faraday::UploadIO
+ # @example
+ # media = Legacy::Google::APIClient::UploadIO.new('mymovie.m4v', 'video/mp4')
+ class UploadIO < Faraday::UploadIO
+
+ # @return [Fixnum] Size of chunks to upload. Default is nil, meaning upload the entire file in a single request
+ attr_accessor :chunk_size
+
+ ##
+ # Get the length of the stream
+ #
+ # @return [Fixnum]
+ # Length of stream, in bytes
+ def length
+ io.respond_to?(:length) ? io.length : File.size(local_path)
+ end
+ end
+
+ ##
+ # Wraps an input stream and limits data to a given range
+ #
+ # @example
+ # chunk = Legacy::Google::APIClient::RangedIO.new(io, 0, 1000)
+ class RangedIO
+ ##
+ # Bind an input stream to a specific range.
+ #
+ # @param [IO] io
+ # Source input stream
+ # @param [Fixnum] offset
+ # Starting offset of the range
+ # @param [Fixnum] length
+ # Length of range
+ def initialize(io, offset, length)
+ @io = io
+ @offset = offset
+ @length = length
+ self.rewind
+ end
+
+ ##
+ # @see IO#read
+ def read(amount = nil, buf = nil)
+ buffer = buf || ''
+ if amount.nil?
+ size = @length - @pos
+ done = ''
+ elsif amount == 0
+ size = 0
+ done = ''
+ else
+ size = [@length - @pos, amount].min
+ done = nil
+ end
+
+ if size > 0
+ result = @io.read(size)
+ result.force_encoding("BINARY") if result.respond_to?(:force_encoding)
+ buffer << result if result
+ @pos = @pos + size
+ end
+
+ if buffer.length > 0
+ buffer
+ else
+ done
+ end
+ end
+
+ ##
+ # @see IO#rewind
+ def rewind
+ self.pos = 0
+ end
+
+ ##
+ # @see IO#pos
+ def pos
+ @pos
+ end
+
+ ##
+ # @see IO#pos=
+ def pos=(pos)
+ @pos = pos
+ @io.pos = @offset + pos
+ end
+ end
+
+ ##
+ # Resumable uploader.
+ #
+ class ResumableUpload < Request
+ # @return [Fixnum] Max bytes to send in a single request
+ attr_accessor :chunk_size
+
+ ##
+ # Creates a new uploader.
+ #
+ # @param [Hash] options
+ # Request options
+ def initialize(options={})
+ super options
+ self.uri = options[:uri]
+ self.http_method = :put
+ @offset = options[:offset] || 0
+ @complete = false
+ @expired = false
+ end
+
+ ##
+ # Sends all remaining chunks to the server
+ #
+ # @deprecated Pass the instance to {Legacy::Google::APIClient#execute} instead
+ #
+ # @param [Legacy::Google::APIClient] api_client
+ # API Client instance to use for sending
+ def send_all(api_client)
+ result = nil
+ until complete?
+ result = send_chunk(api_client)
+ break unless result.status == 308
+ end
+ return result
+ end
+
+
+ ##
+ # Sends the next chunk to the server
+ #
+ # @deprecated Pass the instance to {Legacy::Google::APIClient#execute} instead
+ #
+ # @param [Legacy::Google::APIClient] api_client
+ # API Client instance to use for sending
+ def send_chunk(api_client)
+ return api_client.execute(self)
+ end
+
+ ##
+ # Check if upload is complete
+ #
+ # @return [TrueClass, FalseClass]
+ # Whether or not the upload complete successfully
+ def complete?
+ return @complete
+ end
+
+ ##
+ # Check if the upload URL expired (upload not completed in alotted time.)
+ # Expired uploads must be restarted from the beginning
+ #
+ # @return [TrueClass, FalseClass]
+ # Whether or not the upload has expired and can not be resumed
+ def expired?
+ return @expired
+ end
+
+ ##
+ # Check if upload is resumable. That is, neither complete nor expired
+ #
+ # @return [TrueClass, FalseClass] True if upload can be resumed
+ def resumable?
+ return !(self.complete? or self.expired?)
+ end
+
+ ##
+ # Convert to an HTTP request. Returns components in order of method, URI,
+ # request headers, and body
+ #
+ # @api private
+ #
+ # @return [Array<(Symbol, Addressable::URI, Hash, [#read,#to_str])>]
+ def to_http_request
+ if @complete
+ raise Legacy::Google::APIClient::ClientError, "Upload already complete"
+ elsif @offset.nil?
+ self.headers.update({
+ 'Content-Length' => "0",
+ 'Content-Range' => "bytes */#{media.length}" })
+ else
+ start_offset = @offset
+ remaining = self.media.length - start_offset
+ chunk_size = self.media.chunk_size || self.chunk_size || self.media.length
+ content_length = [remaining, chunk_size].min
+ chunk = RangedIO.new(self.media.io, start_offset, content_length)
+ end_offset = start_offset + content_length - 1
+ self.headers.update({
+ 'Content-Length' => "#{content_length}",
+ 'Content-Type' => self.media.content_type,
+ 'Content-Range' => "bytes #{start_offset}-#{end_offset}/#{media.length}" })
+ self.body = chunk
+ end
+ super
+ end
+
+ ##
+ # Check the result from the server, updating the offset and/or location
+ # if available.
+ #
+ # @api private
+ #
+ # @param [Faraday::Response] response
+ # HTTP response
+ #
+ # @return [Legacy::Google::APIClient::Result]
+ # Processed API response
+ def process_http_response(response)
+ case response.status
+ when 200...299
+ @complete = true
+ when 308
+ range = response.headers['range']
+ if range
+ @offset = range.scan(/\d+/).collect{|x| Integer(x)}.last + 1
+ end
+ if response.headers['location']
+ self.uri = response.headers['location']
+ end
+ when 400...499
+ @expired = true
+ when 500...599
+ # Invalidate the offset to mark it needs to be queried on the
+ # next request
+ @offset = nil
+ end
+ return Legacy::Google::APIClient::Result.new(self, response)
+ end
+
+ ##
+ # Hashified verison of the API request
+ #
+ # @return [Hash]
+ def to_hash
+ super.merge(:offset => @offset)
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/railtie.rb b/lib/legacy/google/api_client/railtie.rb
new file mode 100644
index 00000000000..cc941b763c7
--- /dev/null
+++ b/lib/legacy/google/api_client/railtie.rb
@@ -0,0 +1,20 @@
+require 'rails/railtie'
+require 'legacy/google/api_client/logging'
+
+module Legacy
+ module Google
+ class APIClient
+
+ ##
+ # Optional support class for Rails. Currently replaces the built-in logger
+ # with Rails' application log.
+ #
+ class Railtie < Rails::Railtie
+ initializer 'google-api-client' do |app|
+ logger = app.config.logger || Rails.logger
+ Legacy::Google::APIClient.logger = logger unless logger.nil?
+ end
+ end
+ end
+ end
+end
diff --git a/lib/google/api_client/reference.rb b/lib/legacy/google/api_client/reference.rb
similarity index 64%
rename from lib/google/api_client/reference.rb
rename to lib/legacy/google/api_client/reference.rb
index 15b34250d74..55728a599fd 100644
--- a/lib/google/api_client/reference.rb
+++ b/lib/legacy/google/api_client/reference.rb
@@ -12,16 +12,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'google/api_client/request'
+require 'legacy/google/api_client/request'
-module Google
- class APIClient
- ##
- # Subclass of Request for backwards compatibility with pre-0.5.0 versions of the library
- #
- # @deprecated
- # use {Google::APIClient::Request} instead
- class Reference < Request
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # Subclass of Request for backwards compatibility with pre-0.5.0 versions of the library
+ #
+ # @deprecated
+ # use {Legacy::Google::APIClient::Request} instead
+ class Reference < Request
+ end
end
end
end
diff --git a/lib/legacy/google/api_client/request.rb b/lib/legacy/google/api_client/request.rb
new file mode 100644
index 00000000000..0e780dfe4db
--- /dev/null
+++ b/lib/legacy/google/api_client/request.rb
@@ -0,0 +1,352 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'faraday'
+require 'faraday/request/multipart'
+require 'compat/multi_json'
+require 'addressable/uri'
+require 'stringio'
+require 'legacy/google/api_client/discovery'
+require 'legacy/google/api_client/logging'
+
+module Legacy
+ module Google
+ class APIClient
+
+ ##
+ # Represents an API request.
+ class Request
+ include Legacy::Google::APIClient::Logging
+
+ MULTIPART_BOUNDARY = "-----------RubyApiMultipartPost".freeze
+
+ # @return [Hash] Request parameters
+ attr_reader :parameters
+ # @return [Hash] Additional HTTP headers
+ attr_reader :headers
+ # @return [Legacy::Google::APIClient::Method] API method to invoke
+ attr_reader :api_method
+ # @return [Legacy::Google::APIClient::UploadIO] File to upload
+ attr_accessor :media
+ # @return [#generated_authenticated_request] User credentials
+ attr_accessor :authorization
+ # @return [TrueClass,FalseClass] True if request should include credentials
+ attr_accessor :authenticated
+ # @return [#read, #to_str] Request body
+ attr_accessor :body
+
+ ##
+ # Build a request
+ #
+ # @param [Hash] options
+ # @option options [Hash, Array] :parameters
+ # Request parameters for the API method.
+ # @option options [Legacy::Google::APIClient::Method] :api_method
+ # API method to invoke. Either :api_method or :uri must be specified
+ # @option options [TrueClass, FalseClass] :authenticated
+ # True if request should include credentials. Implicitly true if
+ # unspecified and :authorization present
+ # @option options [#generate_signed_request] :authorization
+ # OAuth credentials
+ # @option options [Legacy::Google::APIClient::UploadIO] :media
+ # File to upload, if media upload request
+ # @option options [#to_json, #to_hash] :body_object
+ # Main body of the API request. Typically hash or object that can
+ # be serialized to JSON
+ # @option options [#read, #to_str] :body
+ # Raw body to send in POST/PUT requests
+ # @option options [String, Addressable::URI] :uri
+ # URI to request. Either :api_method or :uri must be specified
+ # @option options [String, Symbol] :http_method
+ # HTTP method when requesting a URI
+ def initialize(options={})
+ @parameters = Faraday::Utils::ParamsHash.new
+ @headers = Faraday::Utils::Headers.new
+
+ self.parameters.merge!(options[:parameters]) unless options[:parameters].nil?
+ self.headers.merge!(options[:headers]) unless options[:headers].nil?
+ self.api_method = options[:api_method]
+ self.authenticated = options[:authenticated]
+ self.authorization = options[:authorization]
+
+ # These parameters are handled differently because they're not
+ # parameters to the API method, but rather to the API system.
+ self.parameters['key'] ||= options[:key] if options[:key]
+ self.parameters['userIp'] ||= options[:user_ip] if options[:user_ip]
+
+ if options[:media]
+ self.initialize_media_upload(options)
+ elsif options[:body]
+ self.body = options[:body]
+ elsif options[:body_object]
+ self.headers['Content-Type'] ||= 'application/json'
+ self.body = serialize_body(options[:body_object])
+ else
+ self.body = ''
+ end
+
+ unless self.api_method
+ self.http_method = options[:http_method] || 'GET'
+ self.uri = options[:uri]
+ end
+ end
+
+ # @!attribute [r] upload_type
+ # @return [String] protocol used for upload
+ def upload_type
+ return self.parameters['uploadType'] || self.parameters['upload_type']
+ end
+
+ # @!attribute http_method
+ # @return [Symbol] HTTP method if invoking a URI
+ def http_method
+ return @http_method ||= self.api_method.http_method.to_s.downcase.to_sym
+ end
+
+ def http_method=(new_http_method)
+ if new_http_method.kind_of?(Symbol)
+ @http_method = new_http_method.to_s.downcase.to_sym
+ elsif new_http_method.respond_to?(:to_str)
+ @http_method = new_http_method.to_s.downcase.to_sym
+ else
+ raise TypeError,
+ "Expected String or Symbol, got #{new_http_method.class}."
+ end
+ end
+
+ def api_method=(new_api_method)
+ if new_api_method.nil? || new_api_method.kind_of?(Legacy::Google::APIClient::Method)
+ @api_method = new_api_method
+ else
+ raise TypeError,
+ "Expected Legacy::Google::APIClient::Method, got #{new_api_method.class}."
+ end
+ end
+
+ # @!attribute uri
+ # @return [Addressable::URI] URI to send request
+ def uri
+ return @uri ||= self.api_method.generate_uri(self.parameters)
+ end
+
+ def uri=(new_uri)
+ @uri = Addressable::URI.parse(new_uri)
+ @parameters.update(@uri.query_values) unless @uri.query_values.nil?
+ end
+
+
+ # Transmits the request with the given connection
+ #
+ # @api private
+ #
+ # @param [Faraday::Connection] connection
+ # the connection to transmit with
+ # @param [TrueValue,FalseValue] is_retry
+ # True if request has been previous sent
+ #
+ # @return [Legacy::Google::APIClient::Result]
+ # result of API request
+ def send(connection, is_retry = false)
+ self.body.rewind if is_retry && self.body.respond_to?(:rewind)
+ env = self.to_env(connection)
+ logger.debug { "#{self.class} Sending API request #{env[:method]} #{env[:url].to_s} #{env[:request_headers]}" }
+ http_response = connection.app.call(env)
+ result = self.process_http_response(http_response)
+
+ logger.debug { "#{self.class} Result: #{result.status} #{result.headers}" }
+
+ # Resumamble slightly different than other upload protocols in that it requires at least
+ # 2 requests.
+ if result.status == 200 && self.upload_type == 'resumable' && self.media
+ upload = result.resumable_upload
+ unless upload.complete?
+ logger.debug { "#{self.class} Sending upload body" }
+ result = upload.send(connection)
+ end
+ end
+ return result
+ end
+
+ # Convert to an HTTP request. Returns components in order of method, URI,
+ # request headers, and body
+ #
+ # @api private
+ #
+ # @return [Array<(Symbol, Addressable::URI, Hash, [#read,#to_str])>]
+ def to_http_request
+ request = (
+ if self.api_method
+ self.api_method.generate_request(self.parameters, self.body, self.headers)
+ elsif self.uri
+ unless self.parameters.empty?
+ self.uri.query = Addressable::URI.form_encode(self.parameters)
+ end
+ [self.http_method, self.uri.to_s, self.headers, self.body]
+ end)
+ return request
+ end
+
+ ##
+ # Hashified verison of the API request
+ #
+ # @return [Hash]
+ def to_hash
+ options = {}
+ if self.api_method
+ options[:api_method] = self.api_method
+ options[:parameters] = self.parameters
+ else
+ options[:http_method] = self.http_method
+ options[:uri] = self.uri
+ end
+ options[:headers] = self.headers
+ options[:body] = self.body
+ options[:media] = self.media
+ unless self.authorization.nil?
+ options[:authorization] = self.authorization
+ end
+ return options
+ end
+
+ ##
+ # Prepares the request for execution, building a hash of parts
+ # suitable for sending to Faraday::Connection.
+ #
+ # @api private
+ #
+ # @param [Faraday::Connection] connection
+ # Connection for building the request
+ #
+ # @return [Hash]
+ # Encoded request
+ def to_env(connection)
+ method, uri, headers, body = self.to_http_request
+ http_request = connection.build_request(method) do |req|
+ req.url(uri.to_s)
+ req.headers.update(headers)
+ req.body = body
+ end
+
+ if self.authorization.respond_to?(:generate_authenticated_request)
+ http_request = self.authorization.generate_authenticated_request(
+ :request => http_request,
+ :connection => connection
+ )
+ end
+
+ http_request.to_env(connection)
+ end
+
+ ##
+ # Convert HTTP response to an API Result
+ #
+ # @api private
+ #
+ # @param [Faraday::Response] response
+ # HTTP response
+ #
+ # @return [Legacy::Google::APIClient::Result]
+ # Processed API response
+ def process_http_response(response)
+ Result.new(self, response)
+ end
+
+ protected
+
+ ##
+ # Adjust headers & body for media uploads
+ #
+ # @api private
+ #
+ # @param [Hash] options
+ # @option options [Hash, Array] :parameters
+ # Request parameters for the API method.
+ # @option options [Legacy::Google::APIClient::UploadIO] :media
+ # File to upload, if media upload request
+ # @option options [#to_json, #to_hash] :body_object
+ # Main body of the API request. Typically hash or object that can
+ # be serialized to JSON
+ # @option options [#read, #to_str] :body
+ # Raw body to send in POST/PUT requests
+ def initialize_media_upload(options)
+ self.media = options[:media]
+ case self.upload_type
+ when "media"
+ if options[:body] || options[:body_object]
+ raise ArgumentError, "Can not specify body & body object for simple uploads"
+ end
+ self.headers['Content-Type'] ||= self.media.content_type
+ self.headers['Content-Length'] ||= self.media.length.to_s
+ self.body = self.media
+ when "multipart"
+ unless options[:body_object]
+ raise ArgumentError, "Multipart requested but no body object"
+ end
+ metadata = StringIO.new(serialize_body(options[:body_object]))
+ build_multipart([Faraday::UploadIO.new(metadata, 'application/json', 'file.json'), self.media])
+ when "resumable"
+ file_length = self.media.length
+ self.headers['X-Upload-Content-Type'] = self.media.content_type
+ self.headers['X-Upload-Content-Length'] = file_length.to_s
+ if options[:body_object]
+ self.headers['Content-Type'] ||= 'application/json'
+ self.body = serialize_body(options[:body_object])
+ else
+ self.body = ''
+ end
+ end
+ end
+
+ ##
+ # Assemble a multipart message from a set of parts
+ #
+ # @api private
+ #
+ # @param [Array<[#read,#to_str]>] parts
+ # Array of parts to encode.
+ # @param [String] mime_type
+ # MIME type of the message
+ # @param [String] boundary
+ # Boundary for separating each part of the message
+ def build_multipart(parts, mime_type = 'multipart/related', boundary = MULTIPART_BOUNDARY)
+ env = Faraday::Env.new
+ env.request = Faraday::RequestOptions.new
+ env.request.boundary = boundary
+ env.request_headers = {'Content-Type' => "#{mime_type};boundary=#{boundary}"}
+ multipart = Faraday::Request::Multipart.new
+ self.body = multipart.create_multipart(env, parts.map {|part| [nil, part]})
+ self.headers.update(env[:request_headers])
+ end
+
+ ##
+ # Serialize body object to JSON
+ #
+ # @api private
+ #
+ # @param [#to_json,#to_hash] body
+ # object to serialize
+ #
+ # @return [String]
+ # JSON
+ def serialize_body(body)
+ return body.to_json if body.respond_to?(:to_json)
+ return MultiJson.dump(body.to_hash) if body.respond_to?(:to_hash)
+ raise TypeError, 'Could not convert body object to JSON.' +
+ 'Must respond to :to_json or :to_hash.'
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/result.rb b/lib/legacy/google/api_client/result.rb
new file mode 100644
index 00000000000..1ac94c6c3c8
--- /dev/null
+++ b/lib/legacy/google/api_client/result.rb
@@ -0,0 +1,256 @@
+# Copyright 2010 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Legacy
+ module Google
+ class APIClient
+ ##
+ # This class wraps a result returned by an API call.
+ class Result
+ extend Forwardable
+
+ ##
+ # Init the result
+ #
+ # @param [Legacy::Google::APIClient::Request] request
+ # The original request
+ # @param [Faraday::Response] response
+ # Raw HTTP Response
+ def initialize(request, response)
+ @request = request
+ @response = response
+ @media_upload = reference if reference.kind_of?(ResumableUpload)
+ end
+
+ # @return [Legacy::Google::APIClient::Request] Original request object
+ attr_reader :request
+ # @return [Faraday::Response] HTTP response
+ attr_reader :response
+ # @!attribute [r] reference
+ # @return [Legacy::Google::APIClient::Request] Original request object
+ # @deprecated See {#request}
+ alias_method :reference, :request # For compatibility with pre-beta clients
+
+ # @!attribute [r] status
+ # @return [Fixnum] HTTP status code
+ # @!attribute [r] headers
+ # @return [Hash] HTTP response headers
+ # @!attribute [r] body
+ # @return [String] HTTP response body
+ def_delegators :@response, :status, :headers, :body
+
+ # @!attribute [r] resumable_upload
+ # @return [Legacy::Google::APIClient::ResumableUpload] For resuming media uploads
+ def resumable_upload
+ @media_upload ||= (
+ options = self.reference.to_hash.merge(
+ :uri => self.headers['location'],
+ :media => self.reference.media
+ )
+ Legacy::Google::APIClient::ResumableUpload.new(options)
+ )
+ end
+
+ ##
+ # Get the content type of the response
+ # @!attribute [r] media_type
+ # @return [String]
+ # Value of content-type header
+ def media_type
+ _, content_type = self.headers.detect do |h, v|
+ h.downcase == 'Content-Type'.downcase
+ end
+ if content_type
+ return content_type[/^([^;]*);?.*$/, 1].strip.downcase
+ else
+ return nil
+ end
+ end
+
+ ##
+ # Check if request failed
+ #
+ # @!attribute [r] error?
+ # @return [TrueClass, FalseClass]
+ # true if result of operation is an error
+ def error?
+ return self.response.status >= 400
+ end
+
+ ##
+ # Check if request was successful
+ #
+ # @!attribute [r] success?
+ # @return [TrueClass, FalseClass]
+ # true if result of operation was successful
+ def success?
+ return !self.error?
+ end
+
+ ##
+ # Extracts error messages from the response body
+ #
+ # @!attribute [r] error_message
+ # @return [String]
+ # error message, if available
+ def error_message
+ if self.data?
+ if self.data.respond_to?(:error) &&
+ self.data.error.respond_to?(:message)
+ # You're going to get a terrible error message if the response isn't
+ # parsed successfully as an error.
+ return self.data.error.message
+ elsif self.data['error'] && self.data['error']['message']
+ return self.data['error']['message']
+ end
+ end
+ return self.body
+ end
+
+ ##
+ # Check for parsable data in response
+ #
+ # @!attribute [r] data?
+ # @return [TrueClass, FalseClass]
+ # true if body can be parsed
+ def data?
+ !(self.body.nil? || self.body.empty? || self.media_type != 'application/json')
+ end
+
+ ##
+ # Return parsed version of the response body.
+ #
+ # @!attribute [r] data
+ # @return [Object, Hash, String]
+ # Object if body parsable from API schema, Hash if JSON, raw body if unable to parse
+ def data
+ return @data ||= (begin
+ if self.data?
+ media_type = self.media_type
+ data = self.body
+ case media_type
+ when 'application/json'
+ data = MultiJson.load(data)
+ # Strip data wrapper, if present
+ data = data['data'] if data.has_key?('data')
+ else
+ raise ArgumentError,
+ "Content-Type not supported for parsing: #{media_type}"
+ end
+ if @request.api_method && @request.api_method.response_schema
+ # Automatically parse using the schema designated for the
+ # response of this API method.
+ data = @request.api_method.response_schema.new(data)
+ data
+ else
+ # Otherwise, return the raw unparsed value.
+ # This value must be indexable like a Hash.
+ data
+ end
+ end
+ end)
+ end
+
+ ##
+ # Get the token used for requesting the next page of data
+ #
+ # @!attribute [r] next_page_token
+ # @return [String]
+ # next page token
+ def next_page_token
+ if self.data.respond_to?(:next_page_token)
+ return self.data.next_page_token
+ elsif self.data.respond_to?(:[])
+ return self.data["nextPageToken"]
+ else
+ raise TypeError, "Data object did not respond to #next_page_token."
+ end
+ end
+
+ ##
+ # Build a request for fetching the next page of data
+ #
+ # @return [Legacy::Google::APIClient::Request]
+ # API request for retrieving next page, nil if no page token available
+ def next_page
+ return nil unless self.next_page_token
+ merged_parameters = Hash[self.reference.parameters].merge({
+ self.page_token_param => self.next_page_token
+ })
+ # Because Requests can be coerced to Hashes, we can merge them,
+ # preserving all context except the API method parameters that we're
+ # using for pagination.
+ return Legacy::Google::APIClient::Request.new(
+ Hash[self.reference].merge(:parameters => merged_parameters)
+ )
+ end
+
+ ##
+ # Get the token used for requesting the previous page of data
+ #
+ # @!attribute [r] prev_page_token
+ # @return [String]
+ # previous page token
+ def prev_page_token
+ if self.data.respond_to?(:prev_page_token)
+ return self.data.prev_page_token
+ elsif self.data.respond_to?(:[])
+ return self.data["prevPageToken"]
+ else
+ raise TypeError, "Data object did not respond to #next_page_token."
+ end
+ end
+
+ ##
+ # Build a request for fetching the previous page of data
+ #
+ # @return [Legacy::Google::APIClient::Request]
+ # API request for retrieving previous page, nil if no page token available
+ def prev_page
+ return nil unless self.prev_page_token
+ merged_parameters = Hash[self.reference.parameters].merge({
+ self.page_token_param => self.prev_page_token
+ })
+ # Because Requests can be coerced to Hashes, we can merge them,
+ # preserving all context except the API method parameters that we're
+ # using for pagination.
+ return Legacy::Google::APIClient::Request.new(
+ Hash[self.reference].merge(:parameters => merged_parameters)
+ )
+ end
+
+ ##
+ # Pagination scheme used by this request/response
+ #
+ # @!attribute [r] pagination_type
+ # @return [Symbol]
+ # currently always :token
+ def pagination_type
+ return :token
+ end
+
+ ##
+ # Name of the field that contains the pagination token
+ #
+ # @!attribute [r] page_token_param
+ # @return [String]
+ # currently always 'pageToken'
+ def page_token_param
+ return "pageToken"
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/service.rb b/lib/legacy/google/api_client/service.rb
new file mode 100755
index 00000000000..f17be4452e2
--- /dev/null
+++ b/lib/legacy/google/api_client/service.rb
@@ -0,0 +1,235 @@
+# Copyright 2013 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'legacy/google/api_client'
+require 'legacy/google/api_client/service/stub_generator'
+require 'legacy/google/api_client/service/resource'
+require 'legacy/google/api_client/service/request'
+require 'legacy/google/api_client/service/result'
+require 'legacy/google/api_client/service/batch'
+require 'legacy/google/api_client/service/simple_file_store'
+
+module Legacy
+ module Google
+ class APIClient
+
+ ##
+ # Experimental new programming interface at the API level.
+ # Hides Legacy::Google::APIClient. Designed to be easier to use, with less code.
+ #
+ # @example
+ # calendar = Legacy::Google::APIClient::Service.new('calendar', 'v3')
+ # result = calendar.events.list('calendarId' => 'primary').execute()
+ class Service
+ include Legacy::Google::APIClient::Service::StubGenerator
+ extend Forwardable
+
+ DEFAULT_CACHE_FILE = 'discovery.cache'
+
+ # Cache for discovered APIs.
+ @@discovered = {}
+
+ ##
+ # Creates a new Service.
+ #
+ # @param [String, Symbol] api_name
+ # The name of the API this service will access.
+ # @param [String, Symbol] api_version
+ # The version of the API this service will access.
+ # @param [Hash] options
+ # The configuration parameters for the service.
+ # @option options [Symbol, #generate_authenticated_request] :authorization
+ # (:oauth_1)
+ # The authorization mechanism used by the client. The following
+ # mechanisms are supported out-of-the-box:
+ #
+ # :two_legged_oauth_1
+ # :oauth_1
+ # :oauth_2
+ #
+ # @option options [Boolean] :auto_refresh_token (true)
+ # The setting that controls whether or not the api client attempts to
+ # refresh authorization when a 401 is hit in #execute. If the token does
+ # not support it, this option is ignored.
+ # @option options [String] :application_name
+ # The name of the application using the client.
+ # @option options [String] :application_version
+ # The version number of the application using the client.
+ # @option options [String] :host ("www.googleapis.com")
+ # The API hostname used by the client. This rarely needs to be changed.
+ # @option options [String] :port (443)
+ # The port number used by the client. This rarely needs to be changed.
+ # @option options [String] :discovery_path ("/discovery/v1")
+ # The discovery base path. This rarely needs to be changed.
+ # @option options [String] :ca_file
+ # Optional set of root certificates to use when validating SSL connections.
+ # By default, a bundled set of trusted roots will be used.
+ # @option options [#generate_authenticated_request] :authorization
+ # The authorization mechanism for requests. Used only if
+ # `:authenticated` is `true`.
+ # @option options [TrueClass, FalseClass] :authenticated (default: true)
+ # `true` if requests must be signed or somehow
+ # authenticated, `false` otherwise.
+ # @option options [TrueClass, FalseClass] :gzip (default: true)
+ # `true` if gzip enabled, `false` otherwise.
+ # @option options [Faraday::Connection] :connection
+ # A custom connection to be used for all requests.
+ # @option options [ActiveSupport::Cache::Store, :default] :discovery_cache
+ # A cache store to place the discovery documents for loaded APIs.
+ # Avoids unnecessary roundtrips to the discovery service.
+ # :default loads the default local file cache store.
+ def initialize(api_name, api_version, options = {})
+ @api_name = api_name.to_s
+ if api_version.nil?
+ raise ArgumentError,
+ "API version must be set"
+ end
+ @api_version = api_version.to_s
+ if options && !options.respond_to?(:to_hash)
+ raise ArgumentError,
+ "expected options Hash, got #{options.class}"
+ end
+
+ params = {}
+ [:application_name, :application_version, :authorization, :host, :port,
+ :discovery_path, :auto_refresh_token, :key, :user_ip,
+ :ca_file].each do |option|
+ if options.include? option
+ params[option] = options[option]
+ end
+ end
+
+ @client = Legacy::Google::APIClient.new(params)
+
+ @connection = options[:connection] || @client.connection
+
+ @options = options
+
+ # Initialize cache store. Default to SimpleFileStore if :cache_store
+ # is not provided and we have write permissions.
+ if options.include? :cache_store
+ @cache_store = options[:cache_store]
+ else
+ cache_exists = File.exists?(DEFAULT_CACHE_FILE)
+ if (cache_exists && File.writable?(DEFAULT_CACHE_FILE)) ||
+ (!cache_exists && File.writable?(Dir.pwd))
+ @cache_store = Legacy::Google::APIClient::Service::SimpleFileStore.new(
+ DEFAULT_CACHE_FILE)
+ end
+ end
+
+ # Attempt to read API definition from memory cache.
+ # Not thread-safe, but the worst that can happen is a cache miss.
+ unless @api = @@discovered[[api_name, api_version]]
+ # Attempt to read API definition from cache store, if there is one.
+ # If there's a miss or no cache store, call discovery service.
+ if !@cache_store.nil?
+ @api = @cache_store.fetch("%s/%s" % [api_name, api_version]) do
+ @client.discovered_api(api_name, api_version)
+ end
+ else
+ @api = @client.discovered_api(api_name, api_version)
+ end
+ @@discovered[[api_name, api_version]] = @api
+ end
+
+ generate_call_stubs(self, @api)
+ end
+
+ ##
+ # Returns the authorization mechanism used by the service.
+ #
+ # @return [#generate_authenticated_request] The authorization mechanism.
+ def_delegators :@client, :authorization, :authorization=
+
+ ##
+ # The setting that controls whether or not the service attempts to
+ # refresh authorization when a 401 is hit during an API call.
+ #
+ # @return [Boolean]
+ def_delegators :@client, :auto_refresh_token, :auto_refresh_token=
+
+ ##
+ # The application's API key issued by the API console.
+ #
+ # @return [String] The API key.
+ def_delegators :@client, :key, :key=
+
+ ##
+ # The Faraday/HTTP connection used by this service.
+ #
+ # @return [Faraday::Connection]
+ attr_accessor :connection
+
+ ##
+ # The cache store used for storing discovery documents.
+ #
+ # @return [ActiveSupport::Cache::Store,
+ # Legacy::Google::APIClient::Service::SimpleFileStore,
+ # nil]
+ attr_reader :cache_store
+
+ ##
+ # Prepares a Legacy::Google::APIClient::BatchRequest object to make batched calls.
+ # @param [Array] calls
+ # Optional array of Legacy::Google::APIClient::Service::Request to initialize
+ # the batch request with.
+ # @param [Proc] block
+ # Callback for every call's response. Won't be called if a call defined
+ # a callback of its own.
+ #
+ # @yield [Legacy::Google::APIClient::Service::Result]
+ # block to be called when result ready
+ def batch(calls = nil, &block)
+ Legacy::Google::APIClient::Service::BatchRequest.new(self, calls, &block)
+ end
+
+ ##
+ # Executes an API request.
+ # Do not call directly; this method is only used by Request objects when
+ # executing.
+ #
+ # @param [Legacy::Google::APIClient::Service::Request,
+ # Legacy::Google::APIClient::Service::BatchCall] request
+ # The request to be executed.
+ def execute(request)
+ if request.instance_of? Legacy::Google::APIClient::Service::Request
+ params = {:api_method => request.method,
+ :parameters => request.parameters,
+ :connection => @connection}
+ if request.respond_to? :body
+ if request.body.respond_to? :to_hash
+ params[:body_object] = request.body
+ else
+ params[:body] = request.body
+ end
+ end
+ if request.respond_to? :media
+ params[:media] = request.media
+ end
+ [:authenticated, :gzip].each do |option|
+ if @options.include? option
+ params[option] = @options[option]
+ end
+ end
+ result = @client.execute(params)
+ return Legacy::Google::APIClient::Service::Result.new(request, result)
+ elsif request.instance_of? Legacy::Google::APIClient::Service::BatchRequest
+ @client.execute(request.base_batch, {:connection => @connection})
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/service/batch.rb b/lib/legacy/google/api_client/service/batch.rb
new file mode 100644
index 00000000000..44c3fdcd5a8
--- /dev/null
+++ b/lib/legacy/google/api_client/service/batch.rb
@@ -0,0 +1,112 @@
+# Copyright 2013 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'legacy/google/api_client/service/result'
+require 'legacy/google/api_client/batch'
+
+module Legacy
+ module Google
+ class APIClient
+ class Service
+
+ ##
+ # Helper class to contain the result of an individual batched call.
+ #
+ class BatchedCallResult < Result
+ # @return [Fixnum] Index of the call
+ def call_index
+ return @base_result.response.call_id.to_i - 1
+ end
+ end
+
+ ##
+ #
+ #
+ class BatchRequest
+ ##
+ # Creates a new batch request.
+ # This class shouldn't be instantiated directly, but rather through
+ # Service.batch.
+ #
+ # @param [Array] calls
+ # List of Legacy::Google::APIClient::Service::Request to be made.
+ # @param [Proc] block
+ # Callback for every call's response. Won't be called if a call
+ # defined a callback of its own.
+ #
+ # @yield [Legacy::Google::APIClient::Service::Result]
+ # block to be called when result ready
+ def initialize(service, calls, &block)
+ @service = service
+ @base_batch = Legacy::Google::APIClient::BatchRequest.new
+ @global_callback = block if block_given?
+
+ if calls && calls.length > 0
+ calls.each do |call|
+ add(call)
+ end
+ end
+ end
+
+ ##
+ # Add a new call to the batch request.
+ #
+ # @param [Legacy::Google::APIClient::Service::Request] call
+ # the call to be added.
+ # @param [Proc] block
+ # callback for this call's response.
+ #
+ # @return [Legacy::Google::APIClient::Service::BatchRequest]
+ # the BatchRequest, for chaining
+ #
+ # @yield [Legacy::Google::APIClient::Service::Result]
+ # block to be called when result ready
+ def add(call, &block)
+ if !block_given? && @global_callback.nil?
+ raise BatchError, 'Request needs a block'
+ end
+ callback = block || @global_callback
+ base_call = {
+ :api_method => call.method,
+ :parameters => call.parameters
+ }
+ if call.respond_to? :body
+ if call.body.respond_to? :to_hash
+ base_call[:body_object] = call.body
+ else
+ base_call[:body] = call.body
+ end
+ end
+ @base_batch.add(base_call) do |base_result|
+ result = Legacy::Google::APIClient::Service::BatchedCallResult.new(
+ call, base_result)
+ callback.call(result)
+ end
+ return self
+ end
+
+ ##
+ # Executes the batch request.
+ def execute
+ @service.execute(self)
+ end
+
+ attr_reader :base_batch
+
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/service/request.rb b/lib/legacy/google/api_client/service/request.rb
new file mode 100755
index 00000000000..99c9000a75a
--- /dev/null
+++ b/lib/legacy/google/api_client/service/request.rb
@@ -0,0 +1,146 @@
+# Copyright 2013 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Legacy
+ module Google
+ class APIClient
+ class Service
+ ##
+ # Handles an API request.
+ # This contains a full definition of the request to be made (including
+ # method name, parameters, body and media). The remote API call can be
+ # invoked with execute().
+ class Request
+ ##
+ # Build a request.
+ # This class should not be directly instantiated in user code;
+ # instantiation is handled by the stub methods created on Service and
+ # Resource objects.
+ #
+ # @param [Legacy::Google::APIClient::Service] service
+ # The parent Service instance that will execute the request.
+ # @param [Legacy::Google::APIClient::Method] method
+ # The Method instance that describes the API method invoked by the
+ # request.
+ # @param [Hash] parameters
+ # A Hash of parameter names and values to be sent in the API call.
+ def initialize(service, method, parameters)
+ @service = service
+ @method = method
+ @parameters = parameters
+ @body = nil
+ @media = nil
+
+ metaclass = (class << self; self; end)
+
+ # If applicable, add "body", "body=" and resource-named methods for
+ # retrieving and setting the HTTP body for this request.
+ # Examples of setting the body for files.insert in the Drive API:
+ # request.body = object
+ # request.execute
+ # OR
+ # request.file = object
+ # request.execute
+ # OR
+ # request.body(object).execute
+ # OR
+ # request.file(object).execute
+ # Examples of retrieving the body for files.insert in the Drive API:
+ # object = request.body
+ # OR
+ # object = request.file
+ if method.request_schema
+ body_name = method.request_schema.data['id'].dup
+ body_name[0] = body_name[0].chr.downcase
+ body_name_equals = (body_name + '=').to_sym
+ body_name = body_name.to_sym
+
+ metaclass.send(:define_method, :body) do |*args|
+ if args.length == 1
+ @body = args.first
+ return self
+ elsif args.length == 0
+ return @body
+ else
+ raise ArgumentError,
+ "wrong number of arguments (#{args.length}; expecting 0 or 1)"
+ end
+ end
+
+ metaclass.send(:define_method, :body=) do |body|
+ @body = body
+ end
+
+ metaclass.send(:alias_method, body_name, :body)
+ metaclass.send(:alias_method, body_name_equals, :body=)
+ end
+
+ # If applicable, add "media" and "media=" for retrieving and setting
+ # the media object for this request.
+ # Examples of setting the media object:
+ # request.media = object
+ # request.execute
+ # OR
+ # request.media(object).execute
+ # Example of retrieving the media object:
+ # object = request.media
+ if method.media_upload
+ metaclass.send(:define_method, :media) do |*args|
+ if args.length == 1
+ @media = args.first
+ return self
+ elsif args.length == 0
+ return @media
+ else
+ raise ArgumentError,
+ "wrong number of arguments (#{args.length}; expecting 0 or 1)"
+ end
+ end
+
+ metaclass.send(:define_method, :media=) do |media|
+ @media = media
+ end
+ end
+ end
+
+ ##
+ # Returns the parent service capable of executing this request.
+ #
+ # @return [Legacy::Google::APIClient::Service] The parent service.
+ attr_reader :service
+
+ ##
+ # Returns the Method instance that describes the API method invoked by
+ # the request.
+ #
+ # @return [Legacy::Google::APIClient::Method] The API method description.
+ attr_reader :method
+
+ ##
+ # Contains the Hash of parameter names and values to be sent as the
+ # parameters for the API call.
+ #
+ # @return [Hash] The request parameters.
+ attr_accessor :parameters
+
+ ##
+ # Executes the request.
+ def execute
+ @service.execute(self)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/service/resource.rb b/lib/legacy/google/api_client/service/resource.rb
new file mode 100755
index 00000000000..f4f0f7f11ca
--- /dev/null
+++ b/lib/legacy/google/api_client/service/resource.rb
@@ -0,0 +1,42 @@
+# Copyright 2013 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Legacy
+ module Google
+ class APIClient
+ class Service
+ ##
+ # Handles an API resource.
+ # Simple class that contains API methods and/or child resources.
+ class Resource
+ include Legacy::Google::APIClient::Service::StubGenerator
+
+ ##
+ # Build a resource.
+ # This class should not be directly instantiated in user code; resources
+ # are instantiated by the stub generation mechanism on Service creation.
+ #
+ # @param [Legacy::Google::APIClient::Service] service
+ # The Service instance this resource belongs to.
+ # @param [Legacy::Google::APIClient::API, Legacy::Google::APIClient::Resource] root
+ # The node corresponding to this resource.
+ def initialize(service, root)
+ @service = service
+ generate_call_stubs(service, root)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/service/result.rb b/lib/legacy/google/api_client/service/result.rb
new file mode 100755
index 00000000000..f591dab9f53
--- /dev/null
+++ b/lib/legacy/google/api_client/service/result.rb
@@ -0,0 +1,164 @@
+# Copyright 2013 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Legacy
+ module Google
+ class APIClient
+ class Service
+ ##
+ # Handles an API result.
+ # Wraps around the Legacy::Google::APIClient::Result class, making it easier to
+ # handle the result (e.g. pagination) and keeping it in line with the rest
+ # of the Service programming interface.
+ class Result
+ extend Forwardable
+
+ ##
+ # Init the result.
+ #
+ # @param [Legacy::Google::APIClient::Service::Request] request
+ # The original request
+ # @param [Legacy::Google::APIClient::Result] base_result
+ # The base result to be wrapped
+ def initialize(request, base_result)
+ @request = request
+ @base_result = base_result
+ end
+
+ # @!attribute [r] status
+ # @return [Fixnum] HTTP status code
+ # @!attribute [r] headers
+ # @return [Hash] HTTP response headers
+ # @!attribute [r] body
+ # @return [String] HTTP response body
+ def_delegators :@base_result, :status, :headers, :body
+
+ # @return [Legacy::Google::APIClient::Service::Request] Original request object
+ attr_reader :request
+
+ ##
+ # Get the content type of the response
+ # @!attribute [r] media_type
+ # @return [String]
+ # Value of content-type header
+ def_delegators :@base_result, :media_type
+
+ ##
+ # Check if request failed
+ #
+ # @!attribute [r] error?
+ # @return [TrueClass, FalseClass]
+ # true if result of operation is an error
+ def_delegators :@base_result, :error?
+
+ ##
+ # Check if request was successful
+ #
+ # @!attribute [r] success?
+ # @return [TrueClass, FalseClass]
+ # true if result of operation was successful
+ def_delegators :@base_result, :success?
+
+ ##
+ # Extracts error messages from the response body
+ #
+ # @!attribute [r] error_message
+ # @return [String]
+ # error message, if available
+ def_delegators :@base_result, :error_message
+
+ ##
+ # Check for parsable data in response
+ #
+ # @!attribute [r] data?
+ # @return [TrueClass, FalseClass]
+ # true if body can be parsed
+ def_delegators :@base_result, :data?
+
+ ##
+ # Return parsed version of the response body.
+ #
+ # @!attribute [r] data
+ # @return [Object, Hash, String]
+ # Object if body parsable from API schema, Hash if JSON, raw body if unable to parse
+ def_delegators :@base_result, :data
+
+ ##
+ # Pagination scheme used by this request/response
+ #
+ # @!attribute [r] pagination_type
+ # @return [Symbol]
+ # currently always :token
+ def_delegators :@base_result, :pagination_type
+
+ ##
+ # Name of the field that contains the pagination token
+ #
+ # @!attribute [r] page_token_param
+ # @return [String]
+ # currently always 'pageToken'
+ def_delegators :@base_result, :page_token_param
+
+ ##
+ # Get the token used for requesting the next page of data
+ #
+ # @!attribute [r] next_page_token
+ # @return [String]
+ # next page tokenx =
+ def_delegators :@base_result, :next_page_token
+
+ ##
+ # Get the token used for requesting the previous page of data
+ #
+ # @!attribute [r] prev_page_token
+ # @return [String]
+ # previous page token
+ def_delegators :@base_result, :prev_page_token
+
+ # @!attribute [r] resumable_upload
+ def resumable_upload
+ # TODO(sgomes): implement resumable_upload for Service::Result
+ raise NotImplementedError
+ end
+
+ ##
+ # Build a request for fetching the next page of data
+ #
+ # @return [Legacy::Google::APIClient::Service::Request]
+ # API request for retrieving next page
+ def next_page
+ request = @request.clone
+ # Make a deep copy of the parameters.
+ request.parameters = Marshal.load(Marshal.dump(request.parameters))
+ request.parameters[page_token_param] = self.next_page_token
+ return request
+ end
+
+ ##
+ # Build a request for fetching the previous page of data
+ #
+ # @return [Legacy::Google::APIClient::Service::Request]
+ # API request for retrieving previous page
+ def prev_page
+ request = @request.clone
+ # Make a deep copy of the parameters.
+ request.parameters = Marshal.load(Marshal.dump(request.parameters))
+ request.parameters[page_token_param] = self.prev_page_token
+ return request
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/service/simple_file_store.rb b/lib/legacy/google/api_client/service/simple_file_store.rb
new file mode 100644
index 00000000000..8b37b29f3e5
--- /dev/null
+++ b/lib/legacy/google/api_client/service/simple_file_store.rb
@@ -0,0 +1,153 @@
+# Copyright 2013 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Legacy
+ module Google
+ class APIClient
+ class Service
+
+ # Simple file store to be used in the event no ActiveSupport cache store
+ # is provided. This is not thread-safe, and does not support a number of
+ # features (such as expiration), but it's useful for the simple purpose of
+ # caching discovery documents to disk.
+ # Implements the basic cache methods of ActiveSupport::Cache::Store in a
+ # limited fashion.
+ class SimpleFileStore
+
+ # Creates a new SimpleFileStore.
+ #
+ # @param [String] file_path
+ # The path to the cache file on disk.
+ # @param [Object] options
+ # The options to be used with this SimpleFileStore. Not implemented.
+ def initialize(file_path, options = nil)
+ @file_path = file_path.to_s
+ end
+
+ # Returns true if a key exists in the cache.
+ #
+ # @param [String] name
+ # The name of the key. Will always be converted to a string.
+ # @param [Object] options
+ # The options to be used with this query. Not implemented.
+ def exist?(name, options = nil)
+ read_file
+ @cache.nil? ? nil : @cache.include?(name.to_s)
+ end
+
+ # Fetches data from the cache and returns it, using the given key.
+ # If the key is missing and no block is passed, returns nil.
+ # If the key is missing and a block is passed, executes the block, sets
+ # the key to its value, and returns it.
+ #
+ # @param [String] name
+ # The name of the key. Will always be converted to a string.
+ # @param [Object] options
+ # The options to be used with this query. Not implemented.
+ # @yield [String]
+ # optional block with the default value if the key is missing
+ def fetch(name, options = nil)
+ read_file
+ if block_given?
+ entry = read(name.to_s, options)
+ if entry.nil?
+ value = yield name.to_s
+ write(name.to_s, value)
+ return value
+ else
+ return entry
+ end
+ else
+ return read(name.to_s, options)
+ end
+ end
+
+ # Fetches data from the cache, using the given key.
+ # Returns nil if the key is missing.
+ #
+ # @param [String] name
+ # The name of the key. Will always be converted to a string.
+ # @param [Object] options
+ # The options to be used with this query. Not implemented.
+ def read(name, options = nil)
+ read_file
+ @cache.nil? ? nil : @cache[name.to_s]
+ end
+
+ # Writes the value to the cache, with the key.
+ #
+ # @param [String] name
+ # The name of the key. Will always be converted to a string.
+ # @param [Object] value
+ # The value to be written.
+ # @param [Object] options
+ # The options to be used with this query. Not implemented.
+ def write(name, value, options = nil)
+ read_file
+ @cache = {} if @cache.nil?
+ @cache[name.to_s] = value
+ write_file
+ return nil
+ end
+
+ # Deletes an entry in the cache.
+ # Returns true if an entry is deleted.
+ #
+ # @param [String] name
+ # The name of the key. Will always be converted to a string.
+ # @param [Object] options
+ # The options to be used with this query. Not implemented.
+ def delete(name, options = nil)
+ read_file
+ return nil if @cache.nil?
+ if @cache.include? name.to_s
+ @cache.delete name.to_s
+ write_file
+ return true
+ else
+ return nil
+ end
+ end
+
+ protected
+
+ # Read the entire cache file from disk.
+ # Will avoid reading if there have been no changes.
+ def read_file
+ if !File.exist? @file_path
+ @cache = nil
+ else
+ # Check for changes after our last read or write.
+ if @last_change.nil? || File.mtime(@file_path) > @last_change
+ File.open(@file_path) do |file|
+ @cache = Marshal.load(file)
+ @last_change = file.mtime
+ end
+ end
+ end
+ return @cache
+ end
+
+ # Write the entire cache contents to disk.
+ def write_file
+ File.open(@file_path, 'w') do |file|
+ Marshal.dump(@cache, file)
+ end
+ @last_change = File.mtime(@file_path)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/legacy/google/api_client/service/stub_generator.rb b/lib/legacy/google/api_client/service/stub_generator.rb
new file mode 100755
index 00000000000..abf1116a54e
--- /dev/null
+++ b/lib/legacy/google/api_client/service/stub_generator.rb
@@ -0,0 +1,63 @@
+# Copyright 2013 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'active_support/inflector'
+
+module Legacy
+ module Google
+ class APIClient
+ class Service
+ ##
+ # Auxiliary mixin to generate resource and method stubs.
+ # Used by the Service and Service::Resource classes to generate both
+ # top-level and nested resources and methods.
+ module StubGenerator
+ def generate_call_stubs(service, root)
+ metaclass = (class << self; self; end)
+
+ # Handle resources.
+ root.discovered_resources.each do |resource|
+ method_name = ActiveSupport::Inflector.underscore(resource.name).to_sym
+ if !self.respond_to?(method_name)
+ metaclass.send(:define_method, method_name) do
+ Legacy::Google::APIClient::Service::Resource.new(service, resource)
+ end
+ end
+ end
+
+ # Handle methods.
+ root.discovered_methods.each do |method|
+ method_name = ActiveSupport::Inflector.underscore(method.name).to_sym
+ if !self.respond_to?(method_name)
+ metaclass.send(:define_method, method_name) do |*args|
+ if args.length > 1
+ raise ArgumentError,
+ "wrong number of arguments (#{args.length} for 1)"
+ elsif !args.first.respond_to?(:to_hash) && !args.first.nil?
+ raise ArgumentError,
+ "expected parameter Hash, got #{args.first.class}"
+ else
+ return Legacy::Google::APIClient::Service::Request.new(
+ service, method, args.first
+ )
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/google/api_client/service_account.rb b/lib/legacy/google/api_client/service_account.rb
similarity index 60%
rename from lib/google/api_client/service_account.rb
rename to lib/legacy/google/api_client/service_account.rb
index 3d941ae07cb..fc728f463a6 100644
--- a/lib/google/api_client/service_account.rb
+++ b/lib/legacy/google/api_client/service_account.rb
@@ -12,10 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require 'google/api_client/auth/pkcs12'
-require 'google/api_client/auth/jwt_asserter'
-require 'google/api_client/auth/key_utils'
-require 'google/api_client/auth/compute_service_account'
-require 'google/api_client/auth/storage'
-require 'google/api_client/auth/storages/redis_store'
-require 'google/api_client/auth/storages/file_store'
+require 'legacy/google/api_client/auth/pkcs12'
+require 'legacy/google/api_client/auth/jwt_asserter'
+require 'legacy/google/api_client/auth/key_utils'
+require 'legacy/google/api_client/auth/compute_service_account'
+require 'legacy/google/api_client/auth/storage'
+require 'legacy/google/api_client/auth/storages/redis_store'
+require 'legacy/google/api_client/auth/storages/file_store'
diff --git a/lib/google/api_client/version.rb b/lib/legacy/google/api_client/version.rb
similarity index 73%
rename from lib/google/api_client/version.rb
rename to lib/legacy/google/api_client/version.rb
index edddd808b21..7d86a27a1b8 100644
--- a/lib/google/api_client/version.rb
+++ b/lib/legacy/google/api_client/version.rb
@@ -12,15 +12,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-
-module Google
- class APIClient
- module VERSION
- MAJOR = 0
- MINOR = 8
- TINY = 7
- PATCH = nil
- STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
+module Legacy
+ module Google
+ class APIClient
+ module VERSION
+ MAJOR = 0
+ MINOR = 8
+ TINY = 7
+ PATCH = nil
+ STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
+ end
end
end
end
diff --git a/rakelib/wiki.rake b/rakelib/wiki.rake
index 3e0d97d2e39..c5e5ed39c5a 100644
--- a/rakelib/wiki.rake
+++ b/rakelib/wiki.rake
@@ -18,7 +18,7 @@ the following Google APIs.
WIKI
preferred_apis = {}
require 'google/api_client'
- client = Google::APIClient.new
+ client = Legacy::Google::APIClient.new
for api in client.discovered_apis
if !preferred_apis.has_key?(api.name)
preferred_apis[api.name] = api
diff --git a/spec/google/api_client/auth/storage_spec.rb b/spec/legacy/google/api_client/auth/storage_spec.rb
similarity index 93%
rename from spec/google/api_client/auth/storage_spec.rb
rename to spec/legacy/google/api_client/auth/storage_spec.rb
index d8e5b960c79..bdedeb7d591 100644
--- a/spec/google/api_client/auth/storage_spec.rb
+++ b/spec/legacy/google/api_client/auth/storage_spec.rb
@@ -1,16 +1,16 @@
require 'spec_helper'
-require 'google/api_client'
-require 'google/api_client/version'
+require 'legacy/google/api_client'
+require 'legacy/google/api_client/version'
-describe Google::APIClient::Storage do
- let(:client) { Google::APIClient.new(:application_name => 'API Client Tests') }
- let(:root_path) { File.expand_path(File.join(__FILE__, '..', '..', '..')) }
+describe Legacy::Google::APIClient::Storage do
+ let(:client) { Legacy::Google::APIClient.new(:application_name => 'API Client Tests') }
+ let(:root_path) { File.expand_path(File.join(__FILE__, '..', '..', '..', '..')) }
let(:json_file) { File.expand_path(File.join(root_path, 'fixtures', 'files', 'auth_stored_credentials.json')) }
let(:store) { double }
let(:client_stub) { double }
- subject { Google::APIClient::Storage.new(store) }
+ subject { Legacy::Google::APIClient::Storage.new(store) }
describe 'authorize' do
it 'should authorize' do
diff --git a/spec/google/api_client/auth/storages/file_store_spec.rb b/spec/legacy/google/api_client/auth/storages/file_store_spec.rb
similarity index 84%
rename from spec/google/api_client/auth/storages/file_store_spec.rb
rename to spec/legacy/google/api_client/auth/storages/file_store_spec.rb
index 2963b1d45ba..c10e9aa7d44 100644
--- a/spec/google/api_client/auth/storages/file_store_spec.rb
+++ b/spec/legacy/google/api_client/auth/storages/file_store_spec.rb
@@ -1,10 +1,10 @@
require 'spec_helper'
-require 'google/api_client'
-require 'google/api_client/version'
+require 'legacy/google/api_client'
+require 'legacy/google/api_client/version'
-describe Google::APIClient::FileStore do
- let(:root_path) { File.expand_path(File.join(__FILE__, '..','..','..', '..','..')) }
+describe Legacy::Google::APIClient::FileStore do
+ let(:root_path) { File.expand_path(File.join(__FILE__, '..','..','..', '..','..','..')) }
let(:json_file) { File.expand_path(File.join(root_path, 'fixtures', 'files', 'auth_stored_credentials.json')) }
let(:credentials_hash) {{
@@ -18,7 +18,7 @@
"issued_at"=>1384440275
}}
- subject{Google::APIClient::FileStore.new('a file path')}
+ subject{Legacy::Google::APIClient::FileStore.new('a file path')}
it 'should have a path' do
expect(subject.path).to be == 'a file path'
diff --git a/spec/google/api_client/auth/storages/redis_store_spec.rb b/spec/legacy/google/api_client/auth/storages/redis_store_spec.rb
similarity index 84%
rename from spec/google/api_client/auth/storages/redis_store_spec.rb
rename to spec/legacy/google/api_client/auth/storages/redis_store_spec.rb
index de5abc4a101..9eecb1d0136 100644
--- a/spec/google/api_client/auth/storages/redis_store_spec.rb
+++ b/spec/legacy/google/api_client/auth/storages/redis_store_spec.rb
@@ -1,11 +1,11 @@
require 'spec_helper'
-require 'google/api_client'
-require 'google/api_client/version'
+require 'legacy/google/api_client'
+require 'legacy/google/api_client/version'
-describe Google::APIClient::RedisStore do
- let(:root_path) { File.expand_path(File.join(__FILE__, '..', '..', '..', '..', '..')) }
+describe Legacy::Google::APIClient::RedisStore do
+ let(:root_path) { File.expand_path(File.join(__FILE__, '..', '..', '..', '..', '..', '..')) }
let(:json_file) { File.expand_path(File.join(root_path, 'fixtures', 'files', 'auth_stored_credentials.json')) }
let(:redis) {double}
@@ -20,7 +20,7 @@
"issued_at" => 1384440275
} }
- subject { Google::APIClient::RedisStore.new('a redis instance') }
+ subject { Legacy::Google::APIClient::RedisStore.new('a redis instance') }
it 'should have a redis instance' do
expect(subject.redis).to be == 'a redis instance'
@@ -50,7 +50,7 @@
end
end
context 'with given key' do
- let(:redis_store) { Google::APIClient::RedisStore.new('a redis instance', 'another_google_api_credentials') }
+ let(:redis_store) { Legacy::Google::APIClient::RedisStore.new('a redis instance', 'another_google_api_credentials') }
it 'should use given key' do
expect(redis_store.redis_credentials_key).to be == "another_google_api_credentials"
end
diff --git a/spec/google/api_client/batch_spec.rb b/spec/legacy/google/api_client/batch_spec.rb
similarity index 87%
rename from spec/google/api_client/batch_spec.rb
rename to spec/legacy/google/api_client/batch_spec.rb
index 3aa95a88b61..ecd9ae9405a 100644
--- a/spec/google/api_client/batch_spec.rb
+++ b/spec/legacy/google/api_client/batch_spec.rb
@@ -13,10 +13,10 @@
# limitations under the License.
require 'spec_helper'
-require 'google/api_client'
+require 'legacy/google/api_client'
-RSpec.describe Google::APIClient::BatchRequest do
- CLIENT = Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
+RSpec.describe Legacy::Google::APIClient::BatchRequest do
+ CLIENT = Legacy::Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
after do
# Reset client to not-quite-pristine state
@@ -25,15 +25,15 @@
end
it 'should raise an error if making an empty batch request' do
- batch = Google::APIClient::BatchRequest.new
+ batch = Legacy::Google::APIClient::BatchRequest.new
expect(lambda do
CLIENT.execute(batch)
- end).to raise_error(Google::APIClient::BatchError)
+ end).to raise_error(Legacy::Google::APIClient::BatchError)
end
it 'should allow query parameters in batch requests' do
- batch = Google::APIClient::BatchRequest.new
+ batch = Legacy::Google::APIClient::BatchRequest.new
batch.add(:uri => 'https://example.com', :parameters => {
'a' => '12345'
})
@@ -70,7 +70,7 @@
block_called = 0
ids = ['first_call', 'second_call']
expected_ids = ids.clone
- batch = Google::APIClient::BatchRequest.new do |result|
+ batch = Legacy::Google::APIClient::BatchRequest.new do |result|
block_called += 1
expect(result.status).to eq(200)
expect(expected_ids).to include(result.response.call_id)
@@ -85,7 +85,7 @@
end
it 'should execute both when using individual callbacks' do
- batch = Google::APIClient::BatchRequest.new
+ batch = Legacy::Google::APIClient::BatchRequest.new
call1_returned, call2_returned = false, false
batch.add(@call1) do |result|
@@ -103,12 +103,12 @@
end
it 'should raise an error if using the same call ID more than once' do
- batch = Google::APIClient::BatchRequest.new
+ batch = Legacy::Google::APIClient::BatchRequest.new
expect(lambda do
batch.add(@call1, 'my_id')
batch.add(@call2, 'my_id')
- end).to raise_error(Google::APIClient::BatchError)
+ end).to raise_error(Legacy::Google::APIClient::BatchError)
end
end
@@ -135,7 +135,7 @@
block_called = 0
ids = ['first_call', 'second_call']
expected_ids = ids.clone
- batch = Google::APIClient::BatchRequest.new do |result|
+ batch = Legacy::Google::APIClient::BatchRequest.new do |result|
block_called += 1
expect(expected_ids).to include(result.response.call_id)
expected_ids.delete(result.response.call_id)
@@ -155,7 +155,7 @@
end
it 'should execute both when using individual callbacks' do
- batch = Google::APIClient::BatchRequest.new
+ batch = Legacy::Google::APIClient::BatchRequest.new
call1_returned, call2_returned = false, false
batch.add(@call1) do |result|
@@ -231,10 +231,10 @@
end
it 'should convert to a correct HTTP request' do
- batch = Google::APIClient::BatchRequest.new { |result| }
+ batch = Legacy::Google::APIClient::BatchRequest.new { |result| }
batch.add(@call1, '1').add(@call2, '2')
request = batch.to_env(CLIENT.connection)
- boundary = Google::APIClient::BatchRequest::BATCH_BOUNDARY
+ boundary = Legacy::Google::APIClient::BatchRequest::BATCH_BOUNDARY
expect(request[:method].to_s.downcase).to eq('post')
expect(request[:url].to_s).to eq('https://www.googleapis.com/batch')
expect(request[:request_headers]['Content-Type']).to eq("multipart/mixed;boundary=#{boundary}")
diff --git a/spec/google/api_client/client_secrets_spec.rb b/spec/legacy/google/api_client/client_secrets_spec.rb
similarity index 85%
rename from spec/google/api_client/client_secrets_spec.rb
rename to spec/legacy/google/api_client/client_secrets_spec.rb
index ead9bf7e99a..ee31aa829c5 100644
--- a/spec/google/api_client/client_secrets_spec.rb
+++ b/spec/legacy/google/api_client/client_secrets_spec.rb
@@ -16,15 +16,15 @@
require 'spec_helper'
-require 'google/api_client/client_secrets'
+require 'legacy/google/api_client/client_secrets'
-FIXTURES_PATH = File.expand_path('../../../fixtures', __FILE__)
+FIXTURES_PATH = File.expand_path('../../../../fixtures', __FILE__)
-RSpec.describe Google::APIClient::ClientSecrets do
+RSpec.describe Legacy::Google::APIClient::ClientSecrets do
context 'with JSON file' do
let(:file) { File.join(FIXTURES_PATH, 'files', 'client_secrets.json') }
- subject(:secrets) { Google::APIClient::ClientSecrets.load(file)}
+ subject(:secrets) { Legacy::Google::APIClient::ClientSecrets.load(file)}
it 'should load the correct client ID' do
expect(secrets.client_id).to be == '898243283568.apps.googleusercontent.com'
@@ -50,4 +50,4 @@
end
end
-end
\ No newline at end of file
+end
diff --git a/spec/google/api_client/discovery_spec.rb b/spec/legacy/google/api_client/discovery_spec.rb
similarity index 96%
rename from spec/google/api_client/discovery_spec.rb
rename to spec/legacy/google/api_client/discovery_spec.rb
index d596538cca5..e68890cfad4 100644
--- a/spec/google/api_client/discovery_spec.rb
+++ b/spec/legacy/google/api_client/discovery_spec.rb
@@ -21,13 +21,13 @@
require 'multi_json'
require 'compat/multi_json'
require 'signet/oauth_1/client'
-require 'google/api_client'
+require 'legacy/google/api_client'
-fixtures_path = File.expand_path('../../../fixtures', __FILE__)
+fixtures_path = File.expand_path('../../../../fixtures', __FILE__)
-RSpec.describe Google::APIClient do
+RSpec.describe Legacy::Google::APIClient do
include ConnectionHelpers
- CLIENT = Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
+ CLIENT = Legacy::Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
after do
# Reset client to not-quite-pristine state
@@ -37,17 +37,17 @@
it 'should raise a type error for bogus authorization' do
expect(lambda do
- Google::APIClient.new(:application_name => 'API Client Tests', :authorization => 42)
+ Legacy::Google::APIClient.new(:application_name => 'API Client Tests', :authorization => 42)
end).to raise_error(TypeError)
end
it 'should not be able to retrieve the discovery document for a bogus API' do
expect(lambda do
CLIENT.discovery_document('bogus')
- end).to raise_error(Google::APIClient::TransmissionError)
+ end).to raise_error(Legacy::Google::APIClient::TransmissionError)
expect(lambda do
CLIENT.discovered_api('bogus')
- end).to raise_error(Google::APIClient::TransmissionError)
+ end).to raise_error(Legacy::Google::APIClient::TransmissionError)
end
it 'should raise an error for bogus services' do
@@ -77,7 +77,7 @@
zoo_json = File.join(fixtures_path, 'files', 'zoo.json')
contents = File.open(zoo_json, 'rb') { |io| io.read }
api = CLIENT.register_discovery_document('zoo', 'v1', contents)
- expect(api).to be_kind_of(Google::APIClient::API)
+ expect(api).to be_kind_of(Legacy::Google::APIClient::API)
end
end
@@ -275,7 +275,7 @@
it 'should allow modification to the base URIs for testing purposes' do
# Using a new client instance here to avoid caching rebased discovery doc
prediction_rebase =
- Google::APIClient.new(:application_name => 'API Client Tests').discovered_api('prediction', 'v1.2')
+ Legacy::Google::APIClient.new(:application_name => 'API Client Tests').discovered_api('prediction', 'v1.2')
prediction_rebase.method_base =
'https://testing-domain.example.com/prediction/v1.2/'
@@ -365,7 +365,7 @@
@prediction.training.insert,
{'data' => '12345'}
)
- end).to raise_error(Google::APIClient::ClientError)
+ end).to raise_error(Legacy::Google::APIClient::ClientError)
end
it 'should not be able to execute improperly authorized requests' do
@@ -376,7 +376,7 @@
@prediction.training.insert,
{'data' => '12345'}
)
- end).to raise_error(Google::APIClient::ClientError)
+ end).to raise_error(Legacy::Google::APIClient::ClientError)
end
it 'should correctly handle unnamed parameters' do
diff --git a/spec/google/api_client/gzip_spec.rb b/spec/legacy/google/api_client/gzip_spec.rb
similarity index 94%
rename from spec/google/api_client/gzip_spec.rb
rename to spec/legacy/google/api_client/gzip_spec.rb
index 0539b97d939..43b9fb3c40a 100644
--- a/spec/google/api_client/gzip_spec.rb
+++ b/spec/legacy/google/api_client/gzip_spec.rb
@@ -15,9 +15,9 @@
require 'spec_helper'
-require 'google/api_client'
+require 'legacy/google/api_client'
-RSpec.describe Google::APIClient::Gzip do
+RSpec.describe Legacy::Google::APIClient::Gzip do
def create_connection(&block)
Faraday.new do |b|
@@ -59,7 +59,7 @@ def create_connection(&block)
describe 'with API Client' do
before do
- @client = Google::APIClient.new(:application_name => 'test')
+ @client = Legacy::Google::APIClient.new(:application_name => 'test')
@client.authorization = nil
end
diff --git a/spec/google/api_client/media_spec.rb b/spec/legacy/google/api_client/media_spec.rb
similarity index 84%
rename from spec/google/api_client/media_spec.rb
rename to spec/legacy/google/api_client/media_spec.rb
index 944981b187d..5806cbda7e5 100644
--- a/spec/google/api_client/media_spec.rb
+++ b/spec/legacy/google/api_client/media_spec.rb
@@ -14,21 +14,21 @@
require 'spec_helper'
-require 'google/api_client'
+require 'legacy/google/api_client'
-fixtures_path = File.expand_path('../../../fixtures', __FILE__)
+fixtures_path = File.expand_path('../../../../fixtures', __FILE__)
-RSpec.describe Google::APIClient::UploadIO do
+RSpec.describe Legacy::Google::APIClient::UploadIO do
it 'should reject invalid file paths' do
expect(lambda do
- media = Google::APIClient::UploadIO.new('doesnotexist', 'text/plain')
+ media = Legacy::Google::APIClient::UploadIO.new('doesnotexist', 'text/plain')
end).to raise_error
end
describe 'with a file' do
before do
@file = File.expand_path('files/sample.txt', fixtures_path)
- @media = Google::APIClient::UploadIO.new(@file, 'text/plain')
+ @media = Legacy::Google::APIClient::UploadIO.new(@file, 'text/plain')
end
it 'should report the correct file length' do
@@ -43,7 +43,7 @@
describe 'with StringIO' do
before do
@content = "hello world"
- @media = Google::APIClient::UploadIO.new(StringIO.new(@content), 'text/plain', 'test.txt')
+ @media = Legacy::Google::APIClient::UploadIO.new(StringIO.new(@content), 'text/plain', 'test.txt')
end
it 'should report the correct file length' do
@@ -56,10 +56,10 @@
end
end
-RSpec.describe Google::APIClient::RangedIO do
+RSpec.describe Legacy::Google::APIClient::RangedIO do
before do
@source = StringIO.new("1234567890abcdef")
- @io = Google::APIClient::RangedIO.new(@source, 1, 5)
+ @io = Legacy::Google::APIClient::RangedIO.new(@source, 1, 5)
end
it 'should return the correct range when read entirely' do
@@ -104,8 +104,8 @@
end
-RSpec.describe Google::APIClient::ResumableUpload do
- CLIENT = Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
+RSpec.describe Legacy::Google::APIClient::ResumableUpload do
+ CLIENT = Legacy::Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
after do
# Reset client to not-quite-pristine state
@@ -116,8 +116,8 @@
before do
@drive = CLIENT.discovered_api('drive', 'v2')
@file = File.expand_path('files/sample.txt', fixtures_path)
- @media = Google::APIClient::UploadIO.new(@file, 'text/plain')
- @uploader = Google::APIClient::ResumableUpload.new(
+ @media = Legacy::Google::APIClient::UploadIO.new(@file, 'text/plain')
+ @uploader = Legacy::Google::APIClient::ResumableUpload.new(
:media => @media,
:api_method => @drive.files.insert,
:uri => 'https://www.googleapis.com/upload/drive/v1/files/12345')
@@ -171,7 +171,7 @@
end
def mock_result(status, headers = {})
- reference = Google::APIClient::Reference.new(:api_method => @drive.files.insert)
+ reference = Legacy::Google::APIClient::Reference.new(:api_method => @drive.files.insert)
double('result', :status => status, :headers => headers, :reference => reference)
end
diff --git a/spec/google/api_client/request_spec.rb b/spec/legacy/google/api_client/request_spec.rb
similarity index 72%
rename from spec/google/api_client/request_spec.rb
rename to spec/legacy/google/api_client/request_spec.rb
index c63f750dc6d..a796379a46e 100644
--- a/spec/google/api_client/request_spec.rb
+++ b/spec/legacy/google/api_client/request_spec.rb
@@ -14,13 +14,13 @@
require 'spec_helper'
-require 'google/api_client'
+require 'legacy/google/api_client'
-RSpec.describe Google::APIClient::Request do
- CLIENT = Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
+RSpec.describe Legacy::Google::APIClient::Request do
+ CLIENT = Legacy::Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
it 'should normalize parameter names to strings' do
- request = Google::APIClient::Request.new(:uri => 'https://www.google.com', :parameters => {
+ request = Legacy::Google::APIClient::Request.new(:uri => 'https://www.google.com', :parameters => {
:a => '1', 'b' => '2'
})
expect(request.parameters['a']).to eq('1')
diff --git a/spec/google/api_client/result_spec.rb b/spec/legacy/google/api_client/result_spec.rb
similarity index 90%
rename from spec/google/api_client/result_spec.rb
rename to spec/legacy/google/api_client/result_spec.rb
index 67c63b77cfc..362a651edd3 100644
--- a/spec/google/api_client/result_spec.rb
+++ b/spec/legacy/google/api_client/result_spec.rb
@@ -14,16 +14,16 @@
require 'spec_helper'
-require 'google/api_client'
+require 'legacy/google/api_client'
-RSpec.describe Google::APIClient::Result do
- CLIENT = Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
+RSpec.describe Legacy::Google::APIClient::Result do
+ CLIENT = Legacy::Google::APIClient.new(:application_name => 'API Client Tests') unless defined?(CLIENT)
describe 'with the plus API' do
before do
CLIENT.authorization = nil
@plus = CLIENT.discovered_api('plus', 'v1')
- @reference = Google::APIClient::Reference.new({
+ @reference = Legacy::Google::APIClient::Reference.new({
:api_method => @plus.activities.list,
:parameters => {
'userId' => 'me',
@@ -65,7 +65,7 @@
}
END_OF_STRING
)
- @result = Google::APIClient::Result.new(@reference, @response)
+ @result = Legacy::Google::APIClient::Result.new(@reference, @response)
end
it 'should indicate a successful response' do
@@ -91,7 +91,7 @@
it 'should return the result data correctly' do
expect(@result.data?).to be_truthy
expect(@result.data.class.to_s).to eq(
- 'Google::APIClient::Schema::Plus::V1::ActivityFeed'
+ 'Legacy::Google::APIClient::Schema::Plus::V1::ActivityFeed'
)
expect(@result.data.kind).to eq('plus#activityFeed')
expect(@result.data.etag).to eq('FOO')
@@ -124,7 +124,7 @@
}
END_OF_STRING
)
- @result = Google::APIClient::Result.new(@reference, @response)
+ @result = Legacy::Google::APIClient::Result.new(@reference, @response)
end
it 'should not return a next page token' do
@@ -138,7 +138,7 @@
it 'should return the result data correctly' do
expect(@result.data?).to be_truthy
expect(@result.data.class.to_s).to eq(
- 'Google::APIClient::Schema::Plus::V1::ActivityFeed'
+ 'Legacy::Google::APIClient::Schema::Plus::V1::ActivityFeed'
)
expect(@result.data.kind).to eq('plus#activityFeed')
expect(@result.data.etag).to eq('FOO')
@@ -171,7 +171,7 @@
END_OF_STRING
)
allow(@response).to receive(:status).and_return(400)
- @result = Google::APIClient::Result.new(@reference, @response)
+ @result = Legacy::Google::APIClient::Result.new(@reference, @response)
end
it 'should return error status correctly' do
@@ -188,7 +188,7 @@
allow(@response).to receive(:body).and_return('')
allow(@response).to receive(:status).and_return(204)
allow(@response).to receive(:headers).and_return({})
- @result = Google::APIClient::Result.new(@reference, @response)
+ @result = Legacy::Google::APIClient::Result.new(@reference, @response)
end
it 'should indicate no data is available' do
diff --git a/spec/google/api_client/service_account_spec.rb b/spec/legacy/google/api_client/service_account_spec.rb
similarity index 83%
rename from spec/google/api_client/service_account_spec.rb
rename to spec/legacy/google/api_client/service_account_spec.rb
index 6314cea6bc1..194b83cf33e 100644
--- a/spec/google/api_client/service_account_spec.rb
+++ b/spec/legacy/google/api_client/service_account_spec.rb
@@ -14,17 +14,17 @@
require 'spec_helper'
-require 'google/api_client'
+require 'legacy/google/api_client'
-fixtures_path = File.expand_path('../../../fixtures', __FILE__)
+fixtures_path = File.expand_path('../../../../fixtures', __FILE__)
-RSpec.describe Google::APIClient::KeyUtils do
+RSpec.describe Legacy::Google::APIClient::KeyUtils do
it 'should read PKCS12 files from the filesystem' do
if RUBY_PLATFORM == 'java' && RUBY_VERSION.start_with?('1.8')
pending "Reading from PKCS12 not supported on jruby 1.8.x"
end
path = File.expand_path('files/privatekey.p12', fixtures_path)
- key = Google::APIClient::KeyUtils.load_from_pkcs12(path, 'notasecret')
+ key = Legacy::Google::APIClient::KeyUtils.load_from_pkcs12(path, 'notasecret')
expect(key).not_to eq(nil)
end
@@ -34,26 +34,26 @@
end
path = File.expand_path('files/privatekey.p12', fixtures_path)
content = File.read(path)
- key = Google::APIClient::KeyUtils.load_from_pkcs12(content, 'notasecret')
+ key = Legacy::Google::APIClient::KeyUtils.load_from_pkcs12(content, 'notasecret')
expect(key).not_to eq(nil)
end
it 'should read PEM files from the filesystem' do
path = File.expand_path('files/secret.pem', fixtures_path)
- key = Google::APIClient::KeyUtils.load_from_pem(path, 'notasecret')
+ key = Legacy::Google::APIClient::KeyUtils.load_from_pem(path, 'notasecret')
expect(key).not_to eq(nil)
end
it 'should read PEM files from loaded files' do
path = File.expand_path('files/secret.pem', fixtures_path)
content = File.read(path)
- key = Google::APIClient::KeyUtils.load_from_pem(content, 'notasecret')
+ key = Legacy::Google::APIClient::KeyUtils.load_from_pem(content, 'notasecret')
expect(key).not_to eq(nil)
end
end
-RSpec.describe Google::APIClient::JWTAsserter do
+RSpec.describe Legacy::Google::APIClient::JWTAsserter do
include ConnectionHelpers
before do
@@ -61,7 +61,7 @@
end
it 'should generate valid JWTs' do
- asserter = Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
+ asserter = Legacy::Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
jwt = asserter.to_authorization.to_jwt
expect(jwt).not_to eq(nil)
@@ -84,7 +84,7 @@
}']
end
end
- asserter = Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
+ asserter = Legacy::Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
auth = asserter.authorize('user1@email.com', { :connection => conn })
expect(auth).not_to eq(nil?)
expect(auth.person).to eq('user1@email.com')
@@ -104,7 +104,7 @@
}']
end
end
- asserter = Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
+ asserter = Legacy::Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
auth = asserter.authorize(nil, { :connection => conn })
expect(auth).not_to eq(nil?)
expect(auth.access_token).to eq("1/abcdef1234567890")
@@ -134,7 +134,7 @@
}']
end
end
- asserter = Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
+ asserter = Legacy::Google::APIClient::JWTAsserter.new('client1', 'scope1 scope2', @key)
auth = asserter.authorize(nil, { :connection => conn })
expect(auth).not_to eq(nil?)
expect(auth.access_token).to eq("1/abcdef1234567890")
@@ -146,7 +146,7 @@
end
end
-RSpec.describe Google::APIClient::ComputeServiceAccount do
+RSpec.describe Legacy::Google::APIClient::ComputeServiceAccount do
include ConnectionHelpers
it 'should query metadata server' do
@@ -160,7 +160,7 @@
}']
end
end
- service_account = Google::APIClient::ComputeServiceAccount.new
+ service_account = Legacy::Google::APIClient::ComputeServiceAccount.new
auth = service_account.fetch_access_token!({ :connection => conn })
expect(auth).not_to eq(nil?)
expect(auth["access_token"]).to eq("1/abcdef1234567890")
diff --git a/spec/google/api_client/service_spec.rb b/spec/legacy/google/api_client/service_spec.rb
similarity index 86%
rename from spec/google/api_client/service_spec.rb
rename to spec/legacy/google/api_client/service_spec.rb
index fbbdd53ee98..524f8c5feb1 100644
--- a/spec/google/api_client/service_spec.rb
+++ b/spec/legacy/google/api_client/service_spec.rb
@@ -16,31 +16,31 @@
require 'spec_helper'
-require 'google/api_client'
-require 'google/api_client/service'
+require 'legacy/google/api_client'
+require 'legacy/google/api_client/service'
-fixtures_path = File.expand_path('../../../fixtures', __FILE__)
+fixtures_path = File.expand_path('../../../../fixtures', __FILE__)
-RSpec.describe Google::APIClient::Service do
+RSpec.describe Legacy::Google::APIClient::Service do
include ConnectionHelpers
APPLICATION_NAME = 'API Client Tests'
it 'should error out when called without an API name or version' do
expect(lambda do
- Google::APIClient::Service.new
+ Legacy::Google::APIClient::Service.new
end).to raise_error(ArgumentError)
end
it 'should error out when called without an API version' do
expect(lambda do
- Google::APIClient::Service.new('foo')
+ Legacy::Google::APIClient::Service.new('foo')
end).to raise_error(ArgumentError)
end
it 'should error out when the options hash is not a hash' do
expect(lambda do
- Google::APIClient::Service.new('foo', 'v1', 42)
+ Legacy::Google::APIClient::Service.new('foo', 'v1', 42)
end).to raise_error(ArgumentError)
end
@@ -52,7 +52,7 @@
[200, {}, '{}']
end
end
- adsense = Google::APIClient::Service.new(
+ adsense = Legacy::Google::APIClient::Service.new(
'adsense',
'v1.3',
{
@@ -73,7 +73,7 @@
[200, {}, '{}']
end
end
- adsense = Google::APIClient::Service.new(
+ adsense = Legacy::Google::APIClient::Service.new(
'adsense',
'v1.3',
{
@@ -92,7 +92,7 @@
[200, {}, '{}']
end
end
- adsense = Google::APIClient::Service.new(
+ adsense = Legacy::Google::APIClient::Service.new(
'adsense',
'v1.3',
{
@@ -107,12 +107,12 @@
describe 'with no connection' do
before do
- @adsense = Google::APIClient::Service.new('adsense', 'v1.3',
+ @adsense = Legacy::Google::APIClient::Service.new('adsense', 'v1.3',
{:application_name => APPLICATION_NAME, :cache_store => nil})
end
it 'should return a resource when using a valid resource name' do
- expect(@adsense.accounts).to be_a(Google::APIClient::Service::Resource)
+ expect(@adsense.accounts).to be_a(Legacy::Google::APIClient::Service::Resource)
end
it 'should throw an error when using an invalid resource name' do
@@ -123,7 +123,7 @@
it 'should return a request when using a valid method name' do
req = @adsense.adclients.list
- expect(req).to be_a(Google::APIClient::Service::Request)
+ expect(req).to be_a(Legacy::Google::APIClient::Service::Request)
expect(req.method.id).to eq('adsense.adclients.list')
expect(req.parameters).to be_nil
end
@@ -136,7 +136,7 @@
it 'should return a valid request with parameters' do
req = @adsense.adunits.list(:adClientId => '1')
- expect(req).to be_a(Google::APIClient::Service::Request)
+ expect(req).to be_a(Legacy::Google::APIClient::Service::Request)
expect(req.method.id).to eq('adsense.adunits.list')
expect(req.parameters).not_to be_nil
expect(req.parameters[:adClientId]).to eq('1')
@@ -153,7 +153,7 @@
[200, {}, '{}']
end
end
- prediction = Google::APIClient::Service.new(
+ prediction = Legacy::Google::APIClient::Service.new(
'prediction',
'v1.5',
{
@@ -174,7 +174,7 @@
[200, {}, '{}']
end
end
- prediction = Google::APIClient::Service.new(
+ prediction = Legacy::Google::APIClient::Service.new(
'prediction',
'v1.5',
{
@@ -190,13 +190,13 @@
describe 'with no connection' do
before do
- @prediction = Google::APIClient::Service.new('prediction', 'v1.5',
+ @prediction = Legacy::Google::APIClient::Service.new('prediction', 'v1.5',
{:application_name => APPLICATION_NAME, :cache_store => nil})
end
it 'should return a valid request with a body' do
req = @prediction.trainedmodels.insert(:project => '1').body({'id' => '1'})
- expect(req).to be_a(Google::APIClient::Service::Request)
+ expect(req).to be_a(Legacy::Google::APIClient::Service::Request)
expect(req.method.id).to eq('prediction.trainedmodels.insert')
expect(req.body).to eq({'id' => '1'})
expect(req.parameters).not_to be_nil
@@ -205,7 +205,7 @@
it 'should return a valid request with a body when using resource name' do
req = @prediction.trainedmodels.insert(:project => '1').training({'id' => '1'})
- expect(req).to be_a(Google::APIClient::Service::Request)
+ expect(req).to be_a(Legacy::Google::APIClient::Service::Request)
expect(req.method.id).to eq('prediction.trainedmodels.insert')
expect(req.training).to eq({'id' => '1'})
expect(req.parameters).not_to be_nil
@@ -222,7 +222,7 @@
'description' => 'The best home movie ever made'
}
@file = File.expand_path('files/sample.txt', fixtures_path)
- @media = Google::APIClient::UploadIO.new(@file, 'text/plain')
+ @media = Legacy::Google::APIClient::UploadIO.new(@file, 'text/plain')
end
it 'should make a valid call with an object body and media upload' do
@@ -232,7 +232,7 @@
[200, {}, '{}']
end
end
- drive = Google::APIClient::Service.new(
+ drive = Legacy::Google::APIClient::Service.new(
'drive',
'v2',
{
@@ -248,13 +248,13 @@
describe 'with no connection' do
before do
- @drive = Google::APIClient::Service.new('drive', 'v2',
+ @drive = Legacy::Google::APIClient::Service.new('drive', 'v2',
{:application_name => APPLICATION_NAME, :cache_store => nil})
end
it 'should return a valid request with a body and media upload' do
req = @drive.files.insert(:uploadType => 'multipart').body(@metadata).media(@media)
- expect(req).to be_a(Google::APIClient::Service::Request)
+ expect(req).to be_a(Legacy::Google::APIClient::Service::Request)
expect(req.method.id).to eq('drive.files.insert')
expect(req.body).to eq(@metadata)
expect(req.media).to eq(@media)
@@ -264,7 +264,7 @@
it 'should return a valid request with a body and media upload when using resource name' do
req = @drive.files.insert(:uploadType => 'multipart').file(@metadata).media(@media)
- expect(req).to be_a(Google::APIClient::Service::Request)
+ expect(req).to be_a(Legacy::Google::APIClient::Service::Request)
expect(req.method.id).to eq('drive.files.insert')
expect(req.file).to eq(@metadata)
expect(req.media).to eq(@media)
@@ -276,7 +276,7 @@
describe 'with the Discovery API' do
it 'should make a valid end-to-end request' do
- discovery = Google::APIClient::Service.new('discovery', 'v1',
+ discovery = Legacy::Google::APIClient::Service.new('discovery', 'v1',
{:application_name => APPLICATION_NAME, :authenticated => false,
:cache_store => nil})
result = discovery.apis.get_rest(:api => 'discovery', :version => 'v1').execute
@@ -288,13 +288,13 @@
end
-RSpec.describe Google::APIClient::Service::Result do
+RSpec.describe Legacy::Google::APIClient::Service::Result do
describe 'with the plus API' do
before do
- @plus = Google::APIClient::Service.new('plus', 'v1',
+ @plus = Legacy::Google::APIClient::Service.new('plus', 'v1',
{:application_name => APPLICATION_NAME, :cache_store => nil})
- @reference = Google::APIClient::Reference.new({
+ @reference = Legacy::Google::APIClient::Reference.new({
:api_method => @plus.activities.list.method,
:parameters => {
'userId' => 'me',
@@ -336,8 +336,8 @@
}
END_OF_STRING
allow(@response).to receive(:body).and_return(@body)
- base_result = Google::APIClient::Result.new(@reference, @response)
- @result = Google::APIClient::Service::Result.new(@request, base_result)
+ base_result = Legacy::Google::APIClient::Result.new(@reference, @response)
+ @result = Legacy::Google::APIClient::Service::Result.new(@request, base_result)
end
it 'should indicate a successful response' do
@@ -368,7 +368,7 @@
it 'should return the result data correctly' do
expect(@result.data?).to be_truthy
expect(@result.data.class.to_s).to eq(
- 'Google::APIClient::Schema::Plus::V1::ActivityFeed'
+ 'Legacy::Google::APIClient::Schema::Plus::V1::ActivityFeed'
)
expect(@result.data.kind).to eq('plus#activityFeed')
expect(@result.data.etag).to eq('FOO')
@@ -400,8 +400,8 @@
}
END_OF_STRING
allow(@response).to receive(:body).and_return(@body)
- base_result = Google::APIClient::Result.new(@reference, @response)
- @result = Google::APIClient::Service::Result.new(@request, base_result)
+ base_result = Legacy::Google::APIClient::Result.new(@reference, @response)
+ @result = Legacy::Google::APIClient::Service::Result.new(@request, base_result)
end
it 'should not return a next page token' do
@@ -419,7 +419,7 @@
it 'should return the result data correctly' do
expect(@result.data?).to be_truthy
expect(@result.data.class.to_s).to eq(
- 'Google::APIClient::Schema::Plus::V1::ActivityFeed'
+ 'Legacy::Google::APIClient::Schema::Plus::V1::ActivityFeed'
)
expect(@result.data.kind).to eq('plus#activityFeed')
expect(@result.data.etag).to eq('FOO')
@@ -451,8 +451,8 @@
END_OF_STRING
allow(@response).to receive(:body).and_return(@body)
allow(@response).to receive(:status).and_return(400)
- base_result = Google::APIClient::Result.new(@reference, @response)
- @result = Google::APIClient::Service::Result.new(@request, base_result)
+ base_result = Legacy::Google::APIClient::Result.new(@reference, @response)
+ @result = Legacy::Google::APIClient::Service::Result.new(@request, base_result)
end
it 'should return error status correctly' do
@@ -473,8 +473,8 @@
allow(@response).to receive(:body).and_return('')
allow(@response).to receive(:status).and_return(204)
allow(@response).to receive(:headers).and_return({})
- base_result = Google::APIClient::Result.new(@reference, @response)
- @result = Google::APIClient::Service::Result.new(@request, base_result)
+ base_result = Legacy::Google::APIClient::Result.new(@reference, @response)
+ @result = Legacy::Google::APIClient::Service::Result.new(@request, base_result)
end
it 'should indicate no data is available' do
@@ -492,7 +492,7 @@
end
end
-RSpec.describe Google::APIClient::Service::BatchRequest do
+RSpec.describe Legacy::Google::APIClient::Service::BatchRequest do
include ConnectionHelpers
@@ -503,7 +503,7 @@
[500, {'Content-Type' => 'application/json'}, '{}']
end
end
- @discovery = Google::APIClient::Service.new('discovery', 'v1',
+ @discovery = Legacy::Google::APIClient::Service.new('discovery', 'v1',
{:application_name => APPLICATION_NAME, :authorization => nil,
:cache_store => nil, :connection => @conn})
@calls = [
@@ -522,7 +522,7 @@
describe 'with the discovery API' do
before do
- @discovery = Google::APIClient::Service.new('discovery', 'v1',
+ @discovery = Legacy::Google::APIClient::Service.new('discovery', 'v1',
{:application_name => APPLICATION_NAME, :authorization => nil,
:cache_store => nil})
end
@@ -615,4 +615,4 @@
end
end
end
-end
\ No newline at end of file
+end
diff --git a/spec/google/api_client/simple_file_store_spec.rb b/spec/legacy/google/api_client/simple_file_store_spec.rb
similarity index 93%
rename from spec/google/api_client/simple_file_store_spec.rb
rename to spec/legacy/google/api_client/simple_file_store_spec.rb
index cb7d8984759..e83606a8375 100644
--- a/spec/google/api_client/simple_file_store_spec.rb
+++ b/spec/legacy/google/api_client/simple_file_store_spec.rb
@@ -16,16 +16,16 @@
require 'spec_helper'
-require 'google/api_client/service/simple_file_store'
+require 'legacy/google/api_client/service/simple_file_store'
-RSpec.describe Google::APIClient::Service::SimpleFileStore do
+RSpec.describe Legacy::Google::APIClient::Service::SimpleFileStore do
FILE_NAME = 'test.cache'
describe 'with no cache file' do
before(:each) do
File.delete(FILE_NAME) if File.exists?(FILE_NAME)
- @cache = Google::APIClient::Service::SimpleFileStore.new(FILE_NAME)
+ @cache = Legacy::Google::APIClient::Service::SimpleFileStore.new(FILE_NAME)
end
it 'should return nil when asked if a key exists' do
@@ -64,7 +64,7 @@
describe 'with an existing cache' do
before(:each) do
File.delete(FILE_NAME) if File.exists?(FILE_NAME)
- @cache = Google::APIClient::Service::SimpleFileStore.new(FILE_NAME)
+ @cache = Legacy::Google::APIClient::Service::SimpleFileStore.new(FILE_NAME)
@cache.write('existing_key', 'existing_value')
end
@@ -130,4 +130,4 @@
after(:all) do
File.delete(FILE_NAME) if File.exists?(FILE_NAME)
end
-end
\ No newline at end of file
+end
diff --git a/spec/google/api_client_spec.rb b/spec/legacy/google/api_client_spec.rb
similarity index 96%
rename from spec/google/api_client_spec.rb
rename to spec/legacy/google/api_client_spec.rb
index eb9a59af7b8..3caabddea3f 100644
--- a/spec/google/api_client_spec.rb
+++ b/spec/legacy/google/api_client_spec.rb
@@ -16,7 +16,7 @@
require 'faraday'
require 'signet/oauth_1/client'
-require 'google/api_client'
+require 'legacy/google/api_client'
shared_examples_for 'configurable user agent' do
include ConnectionHelpers
@@ -54,18 +54,18 @@
end
end
-RSpec.describe Google::APIClient do
+RSpec.describe Legacy::Google::APIClient do
include ConnectionHelpers
- let(:client) { Google::APIClient.new(:application_name => 'API Client Tests') }
+ let(:client) { Legacy::Google::APIClient.new(:application_name => 'API Client Tests') }
it "should pass the faraday options provided on initialization to FaraDay configuration block" do
- client = Google::APIClient.new(faraday_option: {timeout: 999})
+ client = Legacy::Google::APIClient.new(faraday_option: {timeout: 999})
expect(client.connection.options.timeout).to be == 999
end
it 'should make its version number available' do
- expect(Google::APIClient::VERSION::STRING).to be_instance_of(String)
+ expect(Legacy::Google::APIClient::VERSION::STRING).to be_instance_of(String)
end
it 'should default to OAuth 2' do
diff --git a/yard/lib/yard/templates/helpers/wiki_helper.rb b/yard/lib/yard/templates/helpers/wiki_helper.rb
index e03dfb66814..f5debde9a12 100644
--- a/yard/lib/yard/templates/helpers/wiki_helper.rb
+++ b/yard/lib/yard/templates/helpers/wiki_helper.rb
@@ -262,7 +262,7 @@ def link_url(url, title = nil, params = {})
# @param [CodeObjects::Base] object the object to get an anchor for
# @return [String] the anchor for a specific object
def anchor_for(object)
- # Method:_Google::APIClient#execute!
+ # Method:_Legacy::Google::APIClient#execute!
case object
when CodeObjects::MethodObject
if object.scope == :instance