1 # Copyright 2010 Google Inc.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
18 require 'google/api_client/discovery'
20 module Google #:nodoc:
22 # This class manages communication with a single API.
25 def initialize(options={})
27 # TODO: What configuration options need to go here?
32 # Returns the parser used by the client.
34 unless @options[:parser]
35 require 'google/api_client/parsers/json_parser'
36 # NOTE: Do not rely on this default value, as it may change
37 @options[:parser] = JSONParser
39 return @options[:parser]
43 # Returns the authorization mechanism used by the client.
45 unless @options[:authorization]
46 require 'signet/oauth_1/client'
47 # NOTE: Do not rely on this default value, as it may change
48 @options[:authorization] = Signet::OAuth1::Client.new(
49 :temporary_credential_uri =>
50 'https://www.google.com/accounts/OAuthGetRequestToken',
52 'https://www.google.com/accounts/OAuthAuthorizeToken',
53 :token_credential_uri =>
54 'https://www.google.com/accounts/OAuthGetAccessToken',
55 :client_credential_key => 'anonymous',
56 :client_credential_secret => 'anonymous'
59 return @options[:authorization]
63 # Returns the HTTP adapter used by the client.
65 return @options[:http_adapter] ||= (begin
66 require 'httpadapter/adapters/net_http'
67 @options[:http_adapter] = HTTPAdapter::NetHTTPRequestAdapter
72 return @options[:discovery_uri] ||= (begin
74 service_id = @options[:service]
75 service_version = @options[:service_version] || 'v1'
76 "http://www.googleapis.com/discovery/0.1/describe" +
80 'Missing required configuration value, :discovery_uri.'
85 def discovery_document
86 return @discovery_document ||= (begin
87 request = ['GET', self.discovery_uri, [], []]
88 response = self.transmit_request(request)
89 status, headers, body = response
91 merged_body = StringIO.new
93 merged_body.write(chunk)
96 JSON.parse(merged_body.string)
98 raise TransmissionError,
99 "Could not retrieve discovery document at: #{self.discovery_uri}"
104 def discovered_services
105 return @discovered_services ||= (begin
106 service_names = self.discovery_document['data'].keys()
108 for service_name in service_names
109 versions = self.discovery_document['data'][service_name]
110 for service_version in versions.keys()
111 service_description =
112 self.discovery_document['data'][service_name][service_version]
113 services << ::Google::APIClient::Service.new(
124 def discovered_service(service_name, service_version='v1')
125 for service in self.discovered_services
126 if service.name == service_name &&
127 service.version.to_s == service_version.to_s
134 def discovered_method(rpc_name, service_version='v1')
135 for service in self.discovered_services
136 # This looks kinda weird, but is not a real problem because there's
137 # almost always only one service, and this is memoized anyhow.
138 if service.version.to_s == service_version.to_s
139 return service.to_h[rpc_name] if service.to_h[rpc_name]
145 def latest_service(service_name)
147 for service in self.discovered_services
148 next if service.name != service_name
149 sortable_version = service.version.gsub(/^v/, '').split('.').map do |v|
152 versions[sortable_version] = service
154 return versions[versions.keys.sort.last]
157 def generate_request(
158 api_method, parameters={}, body='', headers=[], options={})
161 :parser => self.parser,
162 :service_version => 'v1'
164 if api_method.kind_of?(String)
165 api_method = self.discovered_method(
166 api_method, options[:service_version]
168 elsif !api_method.kind_of?(::Google::APIClient::Service)
170 "Expected String or Google::APIClient::Service, " +
171 "got #{api_method.class}."
173 request = api_method.generate_request(parameters, body, headers)
175 request = self.sign_request(request)
180 def execute(api_method, parameters={}, body='', headers=[], options={})
181 request = self.generate_request(
182 api_method, parameters, body, headers, options
184 return self.transmit_request(request)
187 def transmit_request(request, adapter=self.http_adapter)
188 ::HTTPAdapter.transmit(request, adapter)
191 def sign_request(request)
192 if self.authorization.respond_to?(:generate_authenticated_request)
193 return self.authorization.generate_authenticated_request(
198 'Expected authorization mechanism to respond to ' +
199 '#generate_authenticated_request.'
205 require 'google/api_client/version'