diff --git a/lib/google/api_client/service.rb b/lib/google/api_client/service.rb
index 5e4aaf71c..f7261144d 100755
--- a/lib/google/api_client/service.rb
+++ b/lib/google/api_client/service.rb
@@ -30,52 +30,56 @@ module Google
# result = calendar.events.list('calendarId' => 'primary').execute()
class Service
include Google::APIClient::Service::StubGenerator
+ extend Forwardable
- ##
- # 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
- # A custom connection to be used for all requests.
+ # 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.
def initialize(api_name, api_version, options = {})
@api_name = api_name.to_s
if api_version.nil?
@@ -98,35 +102,65 @@ module Google
end
@client = Google::APIClient.new(params)
+ @client.logger = options[:logger] if options.include? :logger
+
+ @connection = options[:connection] || @client.connection
@options = options
- @api = @client.discovered_api(api_name, api_version)
+
+ # Cache discovered APIs in memory.
+ # Not thread-safe, but the worst that can happen is a cache miss.
+ unless @api = @@discovered[[api_name, api_version]]
+ @@discovered[[api_name, api_version]] = @api = @client.discovered_api(
+ api_name, api_version)
+ end
+
generate_call_stubs(self, @api)
end
##
# Logger for the Service.
#
- # @return [Logger] logger instance.
- def logger
- @client.logger
- end
+ # @return [Logger]
+ # The logger instance.
+ def_delegators :@client, :logger, :logger=
##
- # Set the Logger for the Service.
- def logger=(obj)
- @client.logger = obj
- 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
##
# Executes an API request.
# Do not call directly; this method is only used by Request objects when
# executing.
+ #
# @param [Google::APIClient::Service::Request] request
# The request to be executed.
def execute(request)
params = {:api_method => request.method,
- :parameters => request.parameters}
+ :parameters => request.parameters,
+ :connection => @connection}
if request.respond_to? :body
if request.body.respond_to? :to_hash
params[:body_object] = request.body
@@ -137,13 +171,13 @@ module Google
if request.respond_to? :media
params[:media] = request.media
end
- [:connection, :authenticated, :gzip].each do |option|
+ [:authenticated, :gzip].each do |option|
if @options.include? option
params[option] = @options[option]
end
end
result = @client.execute(params)
- return Google::APIClient::Result.new(request, result)
+ return Google::APIClient::Service::Result.new(request, result)
end
end
end
diff --git a/spec/google/api_client/service_spec.rb b/spec/google/api_client/service_spec.rb
index 43e3a718c..464ffda21 100644
--- a/spec/google/api_client/service_spec.rb
+++ b/spec/google/api_client/service_spec.rb
@@ -261,6 +261,17 @@ describe Google::APIClient::Service do
end
end
end
+
+ describe 'with the Discovery API' do
+ it 'should make a valid end-to-end request' do
+ discovery = Google::APIClient::Service.new('discovery', 'v1',
+ {:application_name => APPLICATION_NAME, :authenticated => false})
+ result = discovery.apis.get_rest(:api => 'discovery', :version => 'v1').execute
+ result.should_not be_nil
+ result.data.name.should == 'discovery'
+ result.data.version.should == 'v1'
+ end
+ end
end