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.
17 require 'addressable/uri'
18 require 'google/api_client/discovery'
23 def initialize(options={})
24 # We only need this to do lookups on method ID String values
25 # It's optional, but method ID lookups will fail if the client is
27 @client = options[:client]
28 @version = options[:version] || 'v1'
30 self.api_method = options[:api_method]
31 self.parameters = options[:parameters] || {}
32 # These parameters are handled differently because they're not
33 # parameters to the API method, but rather to the API system.
34 self.parameters['key'] ||= options[:key] if options[:key]
35 self.parameters['userIp'] ||= options[:user_ip] if options[:user_ip]
36 self.headers = options[:headers] || []
38 self.body = options[:body]
39 elsif options[:merged_body]
40 self.merged_body = options[:merged_body]
41 elsif options[:body_object]
42 if options[:body_object].respond_to?(:to_json)
43 serialized_body = options[:body_object].to_json
44 elsif options[:body_object].respond_to?(:to_hash)
45 serialized_body = JSON.generate(options[:body_object].to_hash)
48 'Could not convert body object to JSON.' +
49 'Must respond to :to_json or :to_hash.'
51 self.merged_body = serialized_body
55 unless self.api_method
56 self.http_method = options[:http_method] || 'GET'
57 self.uri = options[:uri]
58 unless self.parameters.empty?
59 self.uri.query_values =
60 (self.uri.query_values || {}).merge(self.parameters)
69 def api_method=(new_api_method)
70 if new_api_method.kind_of?(Google::APIClient::Method) ||
72 @api_method = new_api_method
73 elsif new_api_method.respond_to?(:to_str) ||
74 new_api_method.kind_of?(Symbol)
77 "API method lookup impossible without client instance."
79 new_api_method = new_api_method.to_s
80 # This method of guessing the API is unreliable. This will fail for
81 # APIs where the first segment of the RPC name does not match the
82 # service name. However, this is a fallback mechanism anyway.
83 # Developers should be passing in a reference to the method, rather
84 # than passing in a string or symbol. This should raise an error
85 # in the case of a mismatch.
86 api = new_api_method[/^([^.]+)\./, 1]
87 @api_method = @client.discovered_method(
88 new_api_method, api, @version
91 # Ditch the client reference, we won't need it again.
94 raise ArgumentError, "API method could not be found."
98 "Expected Google::APIClient::Method, got #{new_api_method.class}."
106 def parameters=(new_parameters)
107 # No type-checking needed, the Method class handles this.
108 @parameters = new_parameters
116 if new_body.respond_to?(:each)
119 raise TypeError, "Expected body to respond to :each."
124 return (self.body.inject(StringIO.new) do |accu, chunk|
130 def merged_body=(new_merged_body)
131 if new_merged_body.respond_to?(:string)
132 new_merged_body = new_merged_body.string
133 elsif new_merged_body.respond_to?(:to_str)
134 new_merged_body = new_merged_body.to_str
137 "Expected String or StringIO, got #{new_merged_body.class}."
139 self.body = [new_merged_body]
143 return @headers ||= []
146 def headers=(new_headers)
147 if new_headers.kind_of?(Array) || new_headers.kind_of?(Hash)
148 @headers = new_headers
150 raise TypeError, "Expected Hash or Array, got #{new_headers.class}."
155 return @http_method ||= self.api_method.http_method
158 def http_method=(new_http_method)
159 if new_http_method.kind_of?(Symbol)
160 @http_method = new_http_method.to_s.upcase
161 elsif new_http_method.respond_to?(:to_str)
162 @http_method = new_http_method.to_str.upcase
165 "Expected String or Symbol, got #{new_http_method.class}."
170 return @uri ||= self.api_method.generate_uri(self.parameters)
174 @uri = Addressable::URI.parse(new_uri)
179 return self.api_method.generate_request(
180 self.parameters, self.merged_body, self.headers
183 return [self.http_method, self.uri, self.headers, self.body]
190 options[:api_method] = self.api_method
191 options[:parameters] = self.parameters
193 options[:http_method] = self.http_method
194 options[:uri] = self.uri
196 options[:headers] = self.headers
197 options[:body] = self.body