Updated version sorting code and added authorization shortcuts.
git-svn-id: https://google-api-ruby-client.googlecode.com/svn/trunk@60 c1d61fac-ed7f-fcc1-18f7-ff78120a04ef
This commit is contained in:
parent
c183d6ddfd
commit
3bd7056e86
4
README
4
README
|
@ -17,6 +17,7 @@ APIs.
|
||||||
require 'signet/oauth_1/client'
|
require 'signet/oauth_1/client'
|
||||||
client = Google::APIClient.new(
|
client = Google::APIClient.new(
|
||||||
:service => 'buzz',
|
:service => 'buzz',
|
||||||
|
# Buzz has API-specific endpoints
|
||||||
:authorization => Signet::OAuth1::Client.new(
|
:authorization => Signet::OAuth1::Client.new(
|
||||||
:temporary_credential_uri =>
|
:temporary_credential_uri =>
|
||||||
'https://www.google.com/accounts/OAuthGetRequestToken',
|
'https://www.google.com/accounts/OAuthGetRequestToken',
|
||||||
|
@ -48,8 +49,7 @@ APIs.
|
||||||
# Make an API call
|
# Make an API call
|
||||||
response = client.execute(
|
response = client.execute(
|
||||||
'chili.activities.list',
|
'chili.activities.list',
|
||||||
{'scope' => '@self', 'userId' => '@me', 'alt' => 'json'},
|
{'scope' => '@self', 'userId' => '@me', 'alt' => 'json'}
|
||||||
'', [], {:signed => true}
|
|
||||||
)
|
)
|
||||||
status, headers, body = response
|
status, headers, body = response
|
||||||
|
|
||||||
|
|
|
@ -33,11 +33,11 @@ module Google
|
||||||
@options = {
|
@options = {
|
||||||
# TODO: What configuration options need to go here?
|
# TODO: What configuration options need to go here?
|
||||||
}.merge(options)
|
}.merge(options)
|
||||||
if !self.authorization.respond_to?(:generate_authenticated_request)
|
# Force immediate type-checking and short-cut resolution
|
||||||
raise TypeError,
|
self.parser
|
||||||
'Expected authorization mechanism to respond to ' +
|
self.authorization
|
||||||
'#generate_authenticated_request.'
|
self.http_adapter
|
||||||
end
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -53,8 +53,11 @@ module Google
|
||||||
|
|
||||||
##
|
##
|
||||||
# Returns the authorization mechanism used by the client.
|
# Returns the authorization mechanism used by the client.
|
||||||
|
#
|
||||||
|
# @return [#generate_authenticated_request] The authorization mechanism.
|
||||||
def authorization
|
def authorization
|
||||||
unless @options[:authorization]
|
case @options[:authorization]
|
||||||
|
when :oauth_1, :oauth
|
||||||
require 'signet/oauth_1/client'
|
require 'signet/oauth_1/client'
|
||||||
# NOTE: Do not rely on this default value, as it may change
|
# NOTE: Do not rely on this default value, as it may change
|
||||||
@options[:authorization] = Signet::OAuth1::Client.new(
|
@options[:authorization] = Signet::OAuth1::Client.new(
|
||||||
|
@ -67,10 +70,29 @@ module Google
|
||||||
:client_credential_key => 'anonymous',
|
:client_credential_key => 'anonymous',
|
||||||
:client_credential_secret => 'anonymous'
|
:client_credential_secret => 'anonymous'
|
||||||
)
|
)
|
||||||
|
when nil
|
||||||
|
# No authorization mechanism
|
||||||
|
else
|
||||||
|
if !@options[:authorization].respond_to?(
|
||||||
|
:generate_authenticated_request)
|
||||||
|
raise TypeError,
|
||||||
|
'Expected authorization mechanism to respond to ' +
|
||||||
|
'#generate_authenticated_request.'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return @options[:authorization]
|
return @options[:authorization]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Sets the authorization mechanism used by the client.
|
||||||
|
#
|
||||||
|
# @param [#generate_authenticated_request] new_authorization
|
||||||
|
# The new authorization mechanism.
|
||||||
|
def authorization=(new_authorization)
|
||||||
|
@options[:authorization] = new_authorization
|
||||||
|
return self.authorization
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Returns the HTTP adapter used by the client.
|
# Returns the HTTP adapter used by the client.
|
||||||
def http_adapter
|
def http_adapter
|
||||||
|
@ -204,21 +226,15 @@ module Google
|
||||||
# @param [String, Symbol] service_name The name of the service.
|
# @param [String, Symbol] service_name The name of the service.
|
||||||
#
|
#
|
||||||
# @return [Google::APIClient::Service] The service object.
|
# @return [Google::APIClient::Service] The service object.
|
||||||
def latest_service(service_name)
|
def latest_service_version(service_name)
|
||||||
if !service_name.kind_of?(String) && !service_name.kind_of?(Symbol)
|
if !service_name.kind_of?(String) && !service_name.kind_of?(Symbol)
|
||||||
raise TypeError,
|
raise TypeError,
|
||||||
"Expected String or Symbol, got #{service_name.class}."
|
"Expected String or Symbol, got #{service_name.class}."
|
||||||
end
|
end
|
||||||
service_name = service_name.to_s
|
service_name = service_name.to_s
|
||||||
versions = {}
|
return (self.discovered_services.select do |service|
|
||||||
for service in self.discovered_services
|
service.name == service_name
|
||||||
next if service.name != service_name
|
end).sort.last
|
||||||
sortable_version = service.version.gsub(/^v/, '').split('.').map do |v|
|
|
||||||
v.to_i
|
|
||||||
end
|
|
||||||
versions[sortable_version] = service
|
|
||||||
end
|
|
||||||
return versions[versions.keys.sort.last]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -242,25 +258,31 @@ module Google
|
||||||
# <code>:signed</code> is <code>true</code>.
|
# <code>:signed</code> is <code>true</code>.
|
||||||
# - <code>:signed</code> —
|
# - <code>:signed</code> —
|
||||||
# <code>true</code> if the request must be signed, <code>false</code>
|
# <code>true</code> if the request must be signed, <code>false</code>
|
||||||
# otherwise. Defaults to <code>true</code>.
|
# otherwise. Defaults to <code>true</code> if an authorization
|
||||||
|
# mechanism has been set, <code>false</code> otherwise.
|
||||||
#
|
#
|
||||||
# @return [Array] The generated request.
|
# @return [Array] The generated request.
|
||||||
#
|
#
|
||||||
# @example
|
# @example
|
||||||
# request = client.generate_request(
|
# request = client.generate_request(
|
||||||
# 'chili.activities.list',
|
# 'chili.activities.list',
|
||||||
# {'scope' => '@self', 'userId' => '@me', 'alt' => 'json'},
|
# {'scope' => '@self', 'userId' => '@me', 'alt' => 'json'}
|
||||||
# '', [], {:signed => true}
|
|
||||||
# )
|
# )
|
||||||
# method, uri, headers, body = request
|
# method, uri, headers, body = request
|
||||||
def generate_request(
|
def generate_request(
|
||||||
api_method, parameters={}, body='', headers=[], options={})
|
api_method, parameters={}, body='', headers=[], options={})
|
||||||
options={
|
options={
|
||||||
:signed => true,
|
|
||||||
:parser => self.parser,
|
:parser => self.parser,
|
||||||
:service_version => 'v1',
|
:service_version => 'v1',
|
||||||
:authorization => self.authorization
|
:authorization => self.authorization
|
||||||
}.merge(options)
|
}.merge(options)
|
||||||
|
# The default value for the :signed option depends on whether an
|
||||||
|
# authorization mechanism has been set.
|
||||||
|
if options[:authorization]
|
||||||
|
options = {:signed => true}.merge(options)
|
||||||
|
else
|
||||||
|
options = {:signed => false}.merge(options)
|
||||||
|
end
|
||||||
if api_method.kind_of?(String) || api_method.kind_of?(Symbol)
|
if api_method.kind_of?(String) || api_method.kind_of?(Symbol)
|
||||||
api_method = self.discovered_method(
|
api_method = self.discovered_method(
|
||||||
api_method.to_s, options[:service_version]
|
api_method.to_s, options[:service_version]
|
||||||
|
@ -310,8 +332,7 @@ module Google
|
||||||
# @example
|
# @example
|
||||||
# response = client.execute(
|
# response = client.execute(
|
||||||
# 'chili.activities.list',
|
# 'chili.activities.list',
|
||||||
# {'scope' => '@self', 'userId' => '@me', 'alt' => 'json'},
|
# {'scope' => '@self', 'userId' => '@me', 'alt' => 'json'}
|
||||||
# '', [], {:signed => true}
|
|
||||||
# )
|
# )
|
||||||
# status, headers, body = response
|
# status, headers, body = response
|
||||||
def execute(api_method, parameters={}, body='', headers=[], options={})
|
def execute(api_method, parameters={}, body='', headers=[], options={})
|
||||||
|
|
|
@ -138,6 +138,44 @@ module Google
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Compares two versions of a service.
|
||||||
|
#
|
||||||
|
# @param [Object] other The service to compare.
|
||||||
|
#
|
||||||
|
# @return [Integer]
|
||||||
|
# <code>-1</code> if the service is older than <code>other</code>.
|
||||||
|
# <code>0</code> if the service is the same as <code>other</code>.
|
||||||
|
# <code>1</code> if the service is newer than <code>other</code>.
|
||||||
|
# <code>nil</code> if the service cannot be compared to
|
||||||
|
# <code>other</code>.
|
||||||
|
def <=>(other)
|
||||||
|
# We can only compare versions of the same service
|
||||||
|
if other.kind_of?(self.class) && self.name == other.name
|
||||||
|
split_version = lambda do |version|
|
||||||
|
dotted_version = version[/^v?(\d+(.\d+)*)-?(.*?)?$/, 1]
|
||||||
|
suffix = version[/^v?(\d+(.\d+)*)-?(.*?)?$/, 3]
|
||||||
|
[dotted_version.split('.').map { |v| v.to_i }, suffix]
|
||||||
|
end
|
||||||
|
self_sortable, self_suffix = split_version.call(self.version)
|
||||||
|
other_sortable, other_suffix = split_version.call(other.version)
|
||||||
|
result = self_sortable <=> other_sortable
|
||||||
|
if result != 0
|
||||||
|
return result
|
||||||
|
# If the dotted versions are equal, check the suffix.
|
||||||
|
# An omitted suffix should be sorted after an included suffix.
|
||||||
|
elsif self_suffix == ''
|
||||||
|
return 1
|
||||||
|
elsif other_suffix == ''
|
||||||
|
return -1
|
||||||
|
else
|
||||||
|
return self_suffix <=> other_suffix
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Returns a <code>String</code> representation of the service's state.
|
# Returns a <code>String</code> representation of the service's state.
|
||||||
#
|
#
|
||||||
|
|
|
@ -113,13 +113,13 @@ describe Google::APIClient, 'configured for the prediction API' do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should correctly determine the latest version' do
|
it 'should correctly determine the latest version' do
|
||||||
@client.latest_service('prediction').version.should_not == 'v1'
|
@client.latest_service_version('prediction').version.should_not == 'v1'
|
||||||
@client.latest_service(:prediction).version.should_not == 'v1'
|
@client.latest_service_version(:prediction).version.should_not == 'v1'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should raise an error for bogus services' do
|
it 'should raise an error for bogus services' do
|
||||||
(lambda do
|
(lambda do
|
||||||
@client.latest_service(42)
|
@client.latest_service_version(42)
|
||||||
end).should raise_error(TypeError)
|
end).should raise_error(TypeError)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ describe Google::APIClient, 'configured for the prediction API' do
|
||||||
Google::APIClient::Service.new('magic', 'v2.1', {})
|
Google::APIClient::Service.new('magic', 'v2.1', {})
|
||||||
@client.discovered_services <<
|
@client.discovered_services <<
|
||||||
Google::APIClient::Service.new('magic', 'v10.0', {})
|
Google::APIClient::Service.new('magic', 'v10.0', {})
|
||||||
@client.latest_service('magic').version.should == 'v10.1'
|
@client.latest_service_version('magic').version.should == 'v10.1'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should correctly determine the latest version' do
|
it 'should correctly determine the latest version' do
|
||||||
|
@ -152,21 +152,20 @@ describe Google::APIClient, 'configured for the prediction API' do
|
||||||
Google::APIClient::Service.new('two', 'v1.1-r1c3', {})
|
Google::APIClient::Service.new('two', 'v1.1-r1c3', {})
|
||||||
@client.discovered_services <<
|
@client.discovered_services <<
|
||||||
Google::APIClient::Service.new('two', 'v2', {})
|
Google::APIClient::Service.new('two', 'v2', {})
|
||||||
@client.latest_service('two').version.should == 'v2'
|
@client.discovered_services <<
|
||||||
|
Google::APIClient::Service.new('two', 'v2beta1', {})
|
||||||
|
@client.latest_service_version('two').version.should == 'v2'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should return nil for bogus service names' do
|
it 'should return nil for bogus service names' do
|
||||||
# Sanity check the algorithm
|
# Sanity check the algorithm
|
||||||
@client.latest_service('bogus').should == nil
|
@client.latest_service_version('bogus').should == nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should generate valid requests' do
|
it 'should generate valid requests' do
|
||||||
request = @client.generate_request(
|
request = @client.generate_request(
|
||||||
'prediction.training.insert',
|
'prediction.training.insert',
|
||||||
{'query' => '12345'},
|
{'query' => '12345'}
|
||||||
'',
|
|
||||||
[],
|
|
||||||
{:signed => false}
|
|
||||||
)
|
)
|
||||||
method, uri, headers, body = request
|
method, uri, headers, body = request
|
||||||
method.should == 'POST'
|
method.should == 'POST'
|
||||||
|
@ -179,10 +178,7 @@ describe Google::APIClient, 'configured for the prediction API' do
|
||||||
it 'should generate requests against the correct URIs' do
|
it 'should generate requests against the correct URIs' do
|
||||||
request = @client.generate_request(
|
request = @client.generate_request(
|
||||||
:'prediction.training.insert',
|
:'prediction.training.insert',
|
||||||
{'query' => '12345'},
|
{'query' => '12345'}
|
||||||
'',
|
|
||||||
[],
|
|
||||||
{:signed => false}
|
|
||||||
)
|
)
|
||||||
method, uri, headers, body = request
|
method, uri, headers, body = request
|
||||||
uri.should ==
|
uri.should ==
|
||||||
|
@ -193,10 +189,7 @@ describe Google::APIClient, 'configured for the prediction API' do
|
||||||
prediction = @client.discovered_service('prediction', 'v1')
|
prediction = @client.discovered_service('prediction', 'v1')
|
||||||
request = @client.generate_request(
|
request = @client.generate_request(
|
||||||
prediction.training.insert,
|
prediction.training.insert,
|
||||||
{'query' => '12345'},
|
{'query' => '12345'}
|
||||||
'',
|
|
||||||
[],
|
|
||||||
{:signed => false}
|
|
||||||
)
|
)
|
||||||
method, uri, headers, body = request
|
method, uri, headers, body = request
|
||||||
uri.should ==
|
uri.should ==
|
||||||
|
@ -204,14 +197,12 @@ describe Google::APIClient, 'configured for the prediction API' do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should generate signed requests' do
|
it 'should generate signed requests' do
|
||||||
|
@client.authorization = :oauth_1
|
||||||
@client.authorization.token_credential_key = '12345'
|
@client.authorization.token_credential_key = '12345'
|
||||||
@client.authorization.token_credential_secret = '12345'
|
@client.authorization.token_credential_secret = '12345'
|
||||||
request = @client.generate_request(
|
request = @client.generate_request(
|
||||||
'prediction.training.insert',
|
'prediction.training.insert',
|
||||||
{'query' => '12345'},
|
{'query' => '12345'}
|
||||||
'',
|
|
||||||
[],
|
|
||||||
{:signed => true}
|
|
||||||
)
|
)
|
||||||
method, uri, headers, body = request
|
method, uri, headers, body = request
|
||||||
headers = Hash[headers]
|
headers = Hash[headers]
|
||||||
|
@ -220,14 +211,12 @@ describe Google::APIClient, 'configured for the prediction API' do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should not be able to execute improperly authorized requests' do
|
it 'should not be able to execute improperly authorized requests' do
|
||||||
|
@client.authorization = :oauth_1
|
||||||
@client.authorization.token_credential_key = '12345'
|
@client.authorization.token_credential_key = '12345'
|
||||||
@client.authorization.token_credential_secret = '12345'
|
@client.authorization.token_credential_secret = '12345'
|
||||||
response = @client.execute(
|
response = @client.execute(
|
||||||
'prediction.training.insert',
|
'prediction.training.insert',
|
||||||
{'query' => '12345'},
|
{'query' => '12345'}
|
||||||
'',
|
|
||||||
[],
|
|
||||||
{:signed => true}
|
|
||||||
)
|
)
|
||||||
status, headers, body = response
|
status, headers, body = response
|
||||||
status.should == 401
|
status.should == 401
|
||||||
|
|
|
@ -34,6 +34,24 @@ describe Google::APIClient, 'with default configuration' do
|
||||||
@client.parser.should be(Google::APIClient::JSONParser)
|
@client.parser.should be(Google::APIClient::JSONParser)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'should not use an authorization mechanism' do
|
||||||
|
@client.authorization.should be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Google::APIClient, 'with default oauth configuration' do
|
||||||
|
before do
|
||||||
|
@client = Google::APIClient.new(:authorization => :oauth_1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should make its version number available' do
|
||||||
|
::Google::APIClient::VERSION::STRING.should be_instance_of(String)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should use the default JSON parser' do
|
||||||
|
@client.parser.should be(Google::APIClient::JSONParser)
|
||||||
|
end
|
||||||
|
|
||||||
it 'should use the default OAuth1 client configuration' do
|
it 'should use the default OAuth1 client configuration' do
|
||||||
@client.authorization.temporary_credential_uri.to_s.should ==
|
@client.authorization.temporary_credential_uri.to_s.should ==
|
||||||
'https://www.google.com/accounts/OAuthGetRequestToken'
|
'https://www.google.com/accounts/OAuthGetRequestToken'
|
||||||
|
|
Loading…
Reference in New Issue