A significant update of the client functionality.
* updated to use v0.3 of the discovery API * updated to use httpadapter 1.0.0 * added OAuth 2 support to the command line tool * renamed some switches in the command line tool * added additional configuration capabilities git-svn-id: https://google-api-ruby-client.googlecode.com/svn/trunk@128 c1d61fac-ed7f-fcc1-18f7-ff78120a04ef
This commit is contained in:
parent
1dee705828
commit
286a7152f2
|
@ -1,3 +1,11 @@
|
|||
== 0.2.0
|
||||
|
||||
* updated to use v0.3 of the discovery API
|
||||
* updated to use httpadapter 1.0.0
|
||||
* added OAuth 2 support to the command line tool
|
||||
* renamed some switches in the command line tool
|
||||
* added additional configuration capabilities
|
||||
|
||||
== 0.1.3
|
||||
|
||||
* added support for manual overrides of the discovery URI
|
||||
|
|
2
README
2
README
|
@ -44,7 +44,7 @@ APIs.
|
|||
client.authorization.fetch_token_credential!(:verifier => '12345')
|
||||
|
||||
# Discover available methods
|
||||
method_names = client.discovered_service('buzz').to_h.keys
|
||||
method_names = client.discovered_api('buzz').to_h.keys
|
||||
|
||||
# Make an API call
|
||||
response = client.execute(
|
||||
|
|
292
bin/google-api
292
bin/google-api
|
@ -26,7 +26,8 @@ module Google
|
|||
|
||||
def do_GET(request, response)
|
||||
$verifier ||= Addressable::URI.unencode_component(
|
||||
request.request_uri.to_s[/\?.*oauth_verifier=([^&$]+)(&|$)/, 1]
|
||||
request.request_uri.to_s[/\?.*oauth_verifier=([^&$]+)(&|$)/, 1] ||
|
||||
request.request_uri.to_s[/\?.*code=([^&$]+)(&|$)/, 1]
|
||||
)
|
||||
response.status = WEBrick::HTTPStatus::RC_ACCEPTED
|
||||
# This javascript will auto-close the tab after the
|
||||
|
@ -92,24 +93,24 @@ HTML
|
|||
options[:scope] = s
|
||||
end
|
||||
opts.on(
|
||||
"--client-key <key>", String,
|
||||
"Set the 2-legged OAuth key") do |k|
|
||||
"--client-id <key>", String,
|
||||
"Set the OAuth client id or key") do |k|
|
||||
options[:client_credential_key] = k
|
||||
end
|
||||
opts.on(
|
||||
"--client-secret <secret>", String,
|
||||
"Set the 2-legged OAuth secret") do |s|
|
||||
"Set the OAuth client secret") do |s|
|
||||
options[:client_credential_secret] = s
|
||||
end
|
||||
opts.on(
|
||||
"-s", "--service <name>", String,
|
||||
"Perform discovery on service") do |s|
|
||||
options[:service_name] = s
|
||||
"--api <name>", String,
|
||||
"Perform discovery on API") do |s|
|
||||
options[:api] = s
|
||||
end
|
||||
opts.on(
|
||||
"--service-version <id>", String,
|
||||
"Select service version") do |id|
|
||||
options[:service_version] = id
|
||||
options[:version] = id
|
||||
end
|
||||
opts.on(
|
||||
"--content-type <format>", String,
|
||||
|
@ -162,10 +163,11 @@ HTML
|
|||
|
||||
opts.separator(
|
||||
"\nAvailable commands:\n" +
|
||||
" oauth-login Log a user into an API\n" +
|
||||
" list List the methods available for a service\n" +
|
||||
" execute Execute a method on the API\n" +
|
||||
" irb Start an interactive client session"
|
||||
" oauth-1-login Log a user into an API with OAuth 1.0a\n" +
|
||||
" oauth-2-login Log a user into an API with OAuth 2.0 d10\n" +
|
||||
" list List the methods available for a service\n" +
|
||||
" execute Execute a method on the API\n" +
|
||||
" irb Start an interactive client session"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
@ -180,23 +182,98 @@ HTML
|
|||
self.send(symbol)
|
||||
end
|
||||
|
||||
def client
|
||||
require 'signet/oauth_1/client'
|
||||
require 'yaml'
|
||||
require 'irb'
|
||||
config_file = File.expand_path('~/.google-api.yaml')
|
||||
authorization = nil
|
||||
if File.exist?(config_file)
|
||||
config = open(config_file, 'r') { |file| YAML.load(file.read) }
|
||||
else
|
||||
config = {}
|
||||
end
|
||||
if config["mechanism"]
|
||||
authorization = config["mechanism"].to_sym
|
||||
end
|
||||
|
||||
client = Google::APIClient.new(:authorization => authorization)
|
||||
|
||||
case authorization
|
||||
when :oauth_1
|
||||
if client.authorization &&
|
||||
!client.authorization.kind_of?(Signet::OAuth1::Client)
|
||||
STDERR.puts(
|
||||
"Unexpected authorization mechanism: " +
|
||||
"#{client.authorization.class}"
|
||||
)
|
||||
exit(1)
|
||||
end
|
||||
config = open(config_file, 'r') { |file| YAML.load(file.read) }
|
||||
client.authorization.client_credential_key =
|
||||
config["client_credential_key"]
|
||||
client.authorization.client_credential_secret =
|
||||
config["client_credential_secret"]
|
||||
client.authorization.token_credential_key =
|
||||
config["token_credential_key"]
|
||||
client.authorization.token_credential_secret =
|
||||
config["token_credential_secret"]
|
||||
when :oauth_2
|
||||
if client.authorization &&
|
||||
!client.authorization.kind_of?(Signet::OAuth2::Client)
|
||||
STDERR.puts(
|
||||
"Unexpected authorization mechanism: " +
|
||||
"#{client.authorization.class}"
|
||||
)
|
||||
exit(1)
|
||||
end
|
||||
config = open(config_file, 'r') { |file| YAML.load(file.read) }
|
||||
client.authorization.scope = options[:scope]
|
||||
client.authorization.client_id = config["client_id"]
|
||||
client.authorization.client_secret = config["client_secret"]
|
||||
client.authorization.access_token = config["access_token"]
|
||||
client.authorization.refresh_token = config["refresh_token"]
|
||||
else
|
||||
# Dunno?
|
||||
end
|
||||
|
||||
if options[:discovery_uri]
|
||||
client.discovery_uri = options[:discovery_uri]
|
||||
end
|
||||
|
||||
return client
|
||||
end
|
||||
|
||||
def api_version(api, version)
|
||||
v = version
|
||||
if !version
|
||||
if client.preferred_version(api)
|
||||
v = client.preferred_version(api).version
|
||||
else
|
||||
v = 'v1'
|
||||
end
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
COMMANDS = [
|
||||
:oauth_login,
|
||||
:oauth_1_login,
|
||||
:oauth_2_login,
|
||||
:list,
|
||||
:execute,
|
||||
:irb,
|
||||
:fuzz
|
||||
]
|
||||
|
||||
def oauth_login
|
||||
def oauth_1_login
|
||||
require 'signet/oauth_1/client'
|
||||
require 'launchy'
|
||||
require 'yaml'
|
||||
if options[:client_credential_key] &&
|
||||
options[:client_credential_secret]
|
||||
scope = options[:scope]
|
||||
config = {
|
||||
"scope" => nil,
|
||||
"mechanism" => "oauth_1",
|
||||
"scope" => options[:scope],
|
||||
"client_credential_key" => options[:client_credential_key],
|
||||
"client_credential_secret" => options[:client_credential_secret],
|
||||
"token_credential_key" => nil,
|
||||
|
@ -229,19 +306,8 @@ HTML
|
|||
:client_credential_secret => 'anonymous',
|
||||
:callback => "http://localhost:#{OAUTH_SERVER_PORT}/"
|
||||
)
|
||||
scope = options[:scope]
|
||||
# Special cases
|
||||
case scope
|
||||
when /https:\/\/www\.googleapis\.com\/auth\/buzz/,
|
||||
/https:\/\/www\.googleapis\.com\/auth\/buzz\.readonly/
|
||||
oauth_client.authorization_uri =
|
||||
'https://www.google.com/buzz/api/auth/OAuthAuthorizeToken?' +
|
||||
"domain=#{oauth_client.client_credential_key}&" +
|
||||
"scope=#{scope}&" +
|
||||
"xoauth_displayname=Google%20API%20Client"
|
||||
end
|
||||
oauth_client.fetch_temporary_credential!(:additional_parameters => {
|
||||
:scope => scope,
|
||||
:scope => options[:scope],
|
||||
:xoauth_displayname => 'Google API Client'
|
||||
})
|
||||
|
||||
|
@ -251,7 +317,7 @@ HTML
|
|||
server.start
|
||||
oauth_client.fetch_token_credential!(:verifier => $verifier)
|
||||
config = {
|
||||
"scope" => scope,
|
||||
"scope" => options[:scope],
|
||||
"client_credential_key" =>
|
||||
oauth_client.client_credential_key,
|
||||
"client_credential_secret" =>
|
||||
|
@ -267,34 +333,90 @@ HTML
|
|||
end
|
||||
end
|
||||
|
||||
def oauth_2_login
|
||||
require 'signet/oauth_2/client'
|
||||
require 'launchy'
|
||||
require 'yaml'
|
||||
if !options[:client_credential_key] ||
|
||||
!options[:client_credential_secret]
|
||||
STDERR.puts('No client ID and secret supplied.')
|
||||
exit(1)
|
||||
end
|
||||
if options[:access_token]
|
||||
config = {
|
||||
"mechanism" => "oauth_2",
|
||||
"scope" => options[:scope],
|
||||
"client_id" => options[:client_credential_key],
|
||||
"client_secret" => options[:client_credential_secret],
|
||||
"access_token" => options[:access_token],
|
||||
"refresh_token" => options[:refresh_token]
|
||||
}
|
||||
config_file = File.expand_path('~/.google-api.yaml')
|
||||
open(config_file, 'w') { |file| file.write(YAML.dump(config)) }
|
||||
exit(0)
|
||||
else
|
||||
$verifier = nil
|
||||
# TODO(bobaman): Cross-platform?
|
||||
logger = WEBrick::Log.new('/dev/null')
|
||||
server = WEBrick::HTTPServer.new(
|
||||
:Port => OAUTH_SERVER_PORT,
|
||||
:Logger => logger,
|
||||
:AccessLog => logger
|
||||
)
|
||||
trap("INT") { server.shutdown }
|
||||
|
||||
server.mount("/", OAuthVerifierServlet)
|
||||
|
||||
oauth_client = Signet::OAuth2::Client.new(
|
||||
:authorization_uri =>
|
||||
'https://www.google.com/accounts/o8/oauth2/authorization',
|
||||
:token_credential_uri =>
|
||||
'https://www.google.com/accounts/o8/oauth2/token',
|
||||
:client_id => options[:client_credential_key],
|
||||
:client_secret => options[:client_credential_secret],
|
||||
:redirect_uri => "http://localhost:#{OAUTH_SERVER_PORT}/",
|
||||
:scope => options[:scope]
|
||||
)
|
||||
|
||||
# Launch browser
|
||||
Launchy::Browser.run(oauth_client.authorization_uri.to_s)
|
||||
|
||||
server.start
|
||||
oauth_client.code = $verifier
|
||||
oauth_client.fetch_access_token!
|
||||
config = {
|
||||
"mechanism" => "oauth_2",
|
||||
"scope" => options[:scope],
|
||||
"client_id" => oauth_client.client_id,
|
||||
"client_secret" => oauth_client.client_secret,
|
||||
"access_token" => oauth_client.access_token,
|
||||
"refresh_token" => oauth_client.refresh_token
|
||||
}
|
||||
config_file = File.expand_path('~/.google-api.yaml')
|
||||
open(config_file, 'w') { |file| file.write(YAML.dump(config)) }
|
||||
exit(0)
|
||||
end
|
||||
end
|
||||
|
||||
def list
|
||||
service_name = options[:service_name]
|
||||
unless service_name
|
||||
api = options[:api]
|
||||
unless api
|
||||
STDERR.puts('No service name supplied.')
|
||||
exit(1)
|
||||
end
|
||||
client = Google::APIClient.new(
|
||||
:service => service_name,
|
||||
:authorization => nil
|
||||
)
|
||||
client = Google::APIClient.new(:authorization => nil)
|
||||
if options[:discovery_uri]
|
||||
client.discovery_uri = options[:discovery_uri]
|
||||
end
|
||||
service_version =
|
||||
options[:service_version] ||
|
||||
client.latest_service_version(service_name).version
|
||||
service = client.discovered_service(service_name, service_version)
|
||||
version = api_version(api, options[:version])
|
||||
service = client.discovered_api(api, version)
|
||||
rpcnames = service.to_h.keys
|
||||
puts rpcnames.sort.join("\n")
|
||||
exit(0)
|
||||
end
|
||||
|
||||
def execute
|
||||
require 'signet/oauth_1/client'
|
||||
require 'yaml'
|
||||
config_file = File.expand_path('~/.google-api.yaml')
|
||||
signed = File.exist?(config_file)
|
||||
authorization_type = :oauth_1
|
||||
client = self.client
|
||||
|
||||
# Setup HTTP request data
|
||||
request_body = ''
|
||||
|
@ -308,28 +430,6 @@ HTML
|
|||
headers << ['Content-Type', 'application/json']
|
||||
end
|
||||
|
||||
configure_authorization = lambda do |client|
|
||||
if !client.authorization.kind_of?(Signet::OAuth1::Client)
|
||||
STDERR.puts(
|
||||
"Unexpected authorization mechanism: " +
|
||||
"#{client.authorization.class}"
|
||||
)
|
||||
exit(1)
|
||||
end
|
||||
config = open(config_file, 'r') { |file| YAML.load(file.read) }
|
||||
client.authorization.client_credential_key =
|
||||
config["client_credential_key"]
|
||||
client.authorization.client_credential_secret =
|
||||
config["client_credential_secret"]
|
||||
client.authorization.token_credential_key =
|
||||
config["token_credential_key"]
|
||||
client.authorization.token_credential_secret =
|
||||
config["token_credential_secret"]
|
||||
if client.authorization.token_credential == nil
|
||||
authorization_type = :two_legged_oauth_1
|
||||
end
|
||||
end
|
||||
|
||||
if options[:uri]
|
||||
# Make request with URI manually specified
|
||||
uri = Addressable::URI.parse(options[:uri])
|
||||
|
@ -345,13 +445,8 @@ HTML
|
|||
method = options[:http_method]
|
||||
method ||= request_body == '' ? 'GET' : 'POST'
|
||||
method.upcase!
|
||||
client = Google::APIClient.new(:authorization => authorization_type)
|
||||
if options[:discovery_uri]
|
||||
client.discovery_uri = options[:discovery_uri]
|
||||
end
|
||||
configure_authorization.call(client) if signed
|
||||
request = [method, uri.to_str, headers, [request_body]]
|
||||
request = client.sign_request(request)
|
||||
request = client.generate_authenticated_request(:request => request)
|
||||
response = client.transmit_request(request)
|
||||
status, headers, body = response
|
||||
puts body
|
||||
|
@ -362,25 +457,14 @@ HTML
|
|||
STDERR.puts('No rpcname supplied.')
|
||||
exit(1)
|
||||
end
|
||||
service_name =
|
||||
options[:service_name] || self.rpcname[/^([^\.]+)\./, 1]
|
||||
client = Google::APIClient.new(
|
||||
:service => service_name,
|
||||
:authorization => authorization_type
|
||||
)
|
||||
if options[:discovery_uri]
|
||||
client.discovery_uri = options[:discovery_uri]
|
||||
end
|
||||
configure_authorization.call(client) if signed
|
||||
service_version =
|
||||
options[:service_version] ||
|
||||
client.latest_service_version(service_name).version
|
||||
service = client.discovered_service(service_name, service_version)
|
||||
api = options[:api] || self.rpcname[/^([^\.]+)\./, 1]
|
||||
version = api_version(api, options[:version])
|
||||
service = client.discovered_api(api, version)
|
||||
method = service.to_h[self.rpcname]
|
||||
if !method
|
||||
STDERR.puts(
|
||||
"Method #{self.rpcname} does not exist for " +
|
||||
"#{service_name}-#{service_version}."
|
||||
"#{api}-#{version}."
|
||||
)
|
||||
exit(1)
|
||||
end
|
||||
|
@ -394,7 +478,7 @@ HTML
|
|||
end
|
||||
begin
|
||||
response = client.execute(
|
||||
method, parameters, request_body, headers, {:signed => signed}
|
||||
method, parameters, request_body, headers
|
||||
)
|
||||
status, headers, body = response
|
||||
puts body
|
||||
|
@ -407,37 +491,7 @@ HTML
|
|||
end
|
||||
|
||||
def irb
|
||||
require 'signet/oauth_1/client'
|
||||
require 'yaml'
|
||||
require 'irb'
|
||||
config_file = File.expand_path('~/.google-api.yaml')
|
||||
signed = File.exist?(config_file)
|
||||
|
||||
$client = Google::APIClient.new(
|
||||
:service => options[:service_name],
|
||||
:authorization => (signed ? :oauth_1 : nil)
|
||||
)
|
||||
|
||||
if signed
|
||||
if $client.authorization &&
|
||||
!$client.authorization.kind_of?(Signet::OAuth1::Client)
|
||||
STDERR.puts(
|
||||
"Unexpected authorization mechanism: " +
|
||||
"#{$client.authorization.class}"
|
||||
)
|
||||
exit(1)
|
||||
end
|
||||
config = open(config_file, 'r') { |file| YAML.load(file.read) }
|
||||
$client.authorization.client_credential_key =
|
||||
config["client_credential_key"]
|
||||
$client.authorization.client_credential_secret =
|
||||
config["client_credential_secret"]
|
||||
$client.authorization.token_credential_key =
|
||||
config["token_credential_key"]
|
||||
$client.authorization.token_credential_secret =
|
||||
config["token_credential_secret"]
|
||||
end
|
||||
|
||||
$client = self.client
|
||||
# Otherwise IRB will misinterpret command-line options
|
||||
ARGV.clear
|
||||
IRB.start(__FILE__)
|
||||
|
|
|
@ -319,7 +319,7 @@ def service(service_name, service_version)
|
|||
unless service_version
|
||||
service_version = client.latest_service_version(service_name).version
|
||||
end
|
||||
client.discovered_service(service_name, service_version)
|
||||
client.discovered_api(service_name, service_version)
|
||||
end
|
||||
|
||||
get '/template/:service/:method/' do
|
||||
|
|
|
@ -12,58 +12,125 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
require 'httpadapter'
|
||||
require 'json'
|
||||
require 'stringio'
|
||||
|
||||
require 'google/api_client/errors'
|
||||
require 'google/api_client/discovery'
|
||||
|
||||
module Google
|
||||
# TODO(bobaman): Document all this stuff.
|
||||
|
||||
|
||||
##
|
||||
# This class manages communication with a single API.
|
||||
# This class manages APIs communication.
|
||||
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
|
||||
end
|
||||
|
||||
# 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:
|
||||
# <ul>
|
||||
# <li><code>:two_legged_oauth_1</code></li>
|
||||
# <li><code>:oauth_1</code></li>
|
||||
# <li><code>:oauth_2</code></li>
|
||||
# </ul>
|
||||
# @option options [String] :host ("www.googleapis.com")
|
||||
# The API hostname used by the client. This rarely needs to be changed.
|
||||
# @option options [String] :user_agent ("google-api-ruby-client/{version}")
|
||||
# The user agent used by the client. Most developers will want to
|
||||
# leave this value alone — the API key is the primary mechanism used to
|
||||
# identify an application.
|
||||
def initialize(options={})
|
||||
@options = {
|
||||
:user_agent => (
|
||||
'google-api-ruby-client/' + Google::APIClient::VERSION::STRING
|
||||
)
|
||||
}.merge(options)
|
||||
# Force immediate type-checking and short-cut resolution
|
||||
self.parser
|
||||
self.authorization
|
||||
self.http_adapter
|
||||
# Normalize key to String to allow indifferent access.
|
||||
options = options.inject({}) do |accu, (key, value)|
|
||||
accu[key.to_s] = value
|
||||
accu
|
||||
end
|
||||
# Almost all API usage will have a host of 'www.googleapis.com'.
|
||||
self.host = options["host"] || 'www.googleapis.com'
|
||||
# Most developers will want to leave this value alone.
|
||||
self.user_agent = options["user_agent"] || (
|
||||
'google-api-ruby-client/' + Google::APIClient::VERSION::STRING
|
||||
)
|
||||
# This is mostly a default for the sake of convenience.
|
||||
# Unlike most other options, this one may be nil, so we check for
|
||||
# the presence of the key rather than checking the value.
|
||||
if options.has_key?("parser")
|
||||
self.parser = options["parser"]
|
||||
else
|
||||
require 'google/api_client/parsers/json_parser'
|
||||
# NOTE: Do not rely on this default value, as it may change
|
||||
self.parser = Google::APIClient::JSONParser
|
||||
end
|
||||
# The writer method understands a few Symbols and will generate useful
|
||||
# default authentication mechanisms.
|
||||
self.authorization = options["authorization"] || :oauth_2
|
||||
# The HTTP adapter controls all of the HTTP traffic the client generates.
|
||||
# By default, Net::HTTP is used, but adding support for other clients
|
||||
# is trivial.
|
||||
if options["http_adapter"]
|
||||
self.http_adapter = options["http_adapter"]
|
||||
else
|
||||
require 'httpadapter/adapters/net_http'
|
||||
# NOTE: Do not rely on this default value, as it may change
|
||||
self.http_adapter = HTTPAdapter::NetHTTPAdapter.new
|
||||
end
|
||||
@discovery_uris = {}
|
||||
@discovery_documents = {}
|
||||
@discovered_apis = {}
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Returns the parser used by the client.
|
||||
def parser
|
||||
unless @options[:parser]
|
||||
require 'google/api_client/parsers/json_parser'
|
||||
# NOTE: Do not rely on this default value, as it may change
|
||||
@options[:parser] = JSONParser
|
||||
#
|
||||
# @return [#serialize, #parse]
|
||||
# The parser used by the client. Any object that implements both a
|
||||
# <code>#serialize</code> and a <code>#parse</code> method may be used.
|
||||
# If <code>nil</code>, no parsing will be done.
|
||||
attr_reader :parser
|
||||
|
||||
##
|
||||
# Sets the parser used by the client.
|
||||
#
|
||||
# @param [#serialize, #parse] new_parser
|
||||
# The parser used by the client. Any object that implements both a
|
||||
# <code>#serialize</code> and a <code>#parse</code> method may be used.
|
||||
# If <code>nil</code>, no parsing will be done.
|
||||
def parser=(new_parser)
|
||||
if new_parser &&
|
||||
!new_parser.respond_to?(:serialize) &&
|
||||
!new_parser.respond_to?(:parse)
|
||||
raise TypeError,
|
||||
'Expected parser object to respond to #serialize and #parse.'
|
||||
end
|
||||
return @options[:parser]
|
||||
@parser = new_parser
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the authorization mechanism used by the client.
|
||||
#
|
||||
# @return [#generate_authenticated_request] The authorization mechanism.
|
||||
def authorization
|
||||
case @options[:authorization]
|
||||
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
|
||||
@options[:authorization] = Signet::OAuth1::Client.new(
|
||||
new_authorization = Signet::OAuth1::Client.new(
|
||||
:temporary_credential_uri =>
|
||||
'https://www.google.com/accounts/OAuthGetRequestToken',
|
||||
:authorization_uri =>
|
||||
|
@ -76,79 +143,149 @@ module Google
|
|||
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
|
||||
@options[:authorization] = Signet::OAuth1::Client.new(
|
||||
new_authorization = Signet::OAuth1::Client.new(
|
||||
:client_credential_key => nil,
|
||||
:client_credential_secret => nil,
|
||||
:two_legged => true
|
||||
)
|
||||
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 !@options[:authorization].respond_to?(
|
||||
:generate_authenticated_request)
|
||||
if !new_authorization.respond_to?(:generate_authenticated_request)
|
||||
raise TypeError,
|
||||
'Expected authorization mechanism to respond to ' +
|
||||
'#generate_authenticated_request.'
|
||||
end
|
||||
end
|
||||
return @options[:authorization]
|
||||
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
|
||||
@authorization = new_authorization
|
||||
return @authorization
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the HTTP adapter used by the client.
|
||||
def http_adapter
|
||||
return @options[:http_adapter] ||= (begin
|
||||
require 'httpadapter/adapters/net_http'
|
||||
@options[:http_adapter] = HTTPAdapter::NetHTTPRequestAdapter
|
||||
end)
|
||||
#
|
||||
# @return [HTTPAdapter]
|
||||
# The HTTP adapter object. The object must include the
|
||||
# HTTPAdapter module and conform to its interface.
|
||||
attr_reader :http_adapter
|
||||
|
||||
##
|
||||
# Returns the HTTP adapter used by the client.
|
||||
#
|
||||
# @return [HTTPAdapter]
|
||||
# The HTTP adapter object. The object must include the
|
||||
# HTTPAdapter module and conform to its interface.
|
||||
def http_adapter=(new_http_adapter)
|
||||
if new_http_adapter.kind_of?(HTTPAdapter)
|
||||
@http_adapter = new_http_adapter
|
||||
else
|
||||
raise TypeError, "Expected HTTPAdapter, got #{new_http_adapter.class}."
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# The API hostname used by the client.
|
||||
#
|
||||
# @return [String]
|
||||
# The API hostname. Should almost always be 'www.googleapis.com'.
|
||||
attr_accessor :host
|
||||
|
||||
##
|
||||
# The user agent used by the client.
|
||||
#
|
||||
# @return [String]
|
||||
# The user agent string used in the User-Agent header.
|
||||
attr_accessor :user_agent
|
||||
|
||||
##
|
||||
# Returns the URI for the directory document.
|
||||
#
|
||||
# @return [Addressable::URI] The URI of the directory document.
|
||||
def directory_uri
|
||||
template = Addressable::Template.new(
|
||||
"https://{host}/discovery/v0.3/directory"
|
||||
)
|
||||
return template.expand({
|
||||
"host" => self.host
|
||||
})
|
||||
end
|
||||
|
||||
##
|
||||
# Manually registers a URI as a discovery document for a specific version
|
||||
# of an API.
|
||||
#
|
||||
# @param [String, Symbol] api The service name.
|
||||
# @param [String] version The desired version of the service.
|
||||
# @param [Addressable::URI] uri The URI of the discovery document.
|
||||
def register_discovery_uri(api, version, uri)
|
||||
api = api.to_s
|
||||
version = version || 'v1'
|
||||
@discovery_uris["#{api}:#{version}"] = uri
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the URI for the discovery document.
|
||||
#
|
||||
# @param [String, Symbol] api The service name.
|
||||
# @param [String] version The desired version of the service.
|
||||
# @return [Addressable::URI] The URI of the discovery document.
|
||||
def discovery_uri
|
||||
return @options[:discovery_uri] ||= (begin
|
||||
if @options[:service]
|
||||
service_id = @options[:service]
|
||||
service_version = @options[:service_version] || 'v1'
|
||||
Addressable::URI.parse(
|
||||
"http://www.googleapis.com/discovery/0.1/describe" +
|
||||
"?api=#{service_id}"
|
||||
)
|
||||
else
|
||||
raise ArgumentError,
|
||||
'Missing required configuration value, :discovery_uri.'
|
||||
end
|
||||
def discovery_uri(api, version=nil)
|
||||
api = api.to_s
|
||||
version = version || 'v1'
|
||||
return @discovery_uris["#{api}:#{version}"] ||= (begin
|
||||
template = Addressable::Template.new(
|
||||
"https://{host}/discovery/v0.3/describe/" +
|
||||
"{api}/{version}"
|
||||
)
|
||||
template.expand({
|
||||
"host" => self.host,
|
||||
"api" => api,
|
||||
"version" => version
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
##
|
||||
# Sets the discovery URI for the client.
|
||||
# Manually registers a pre-loaded discovery document for a specific version
|
||||
# of an API.
|
||||
#
|
||||
# @param [Addressable::URI, #to_str, String] new_discovery_uri
|
||||
# The new discovery URI.
|
||||
def discovery_uri=(new_discovery_uri)
|
||||
@options[:discovery_uri] = Addressable::URI.parse(new_discovery_uri)
|
||||
# @param [String, Symbol] api The service name.
|
||||
# @param [String] version The desired version of the service.
|
||||
# @param [String, StringIO] discovery_document
|
||||
# The contents of the discovery document.
|
||||
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}"] =
|
||||
JSON.parse(discovery_document)
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the parsed discovery document.
|
||||
# Returns the parsed directory document.
|
||||
#
|
||||
# @return [Hash] The parsed JSON from the discovery document.
|
||||
def discovery_document
|
||||
return @discovery_document ||= (begin
|
||||
request = ['GET', self.discovery_uri.to_s, [], []]
|
||||
# @return [Hash] The parsed JSON from the directory document.
|
||||
def directory_document
|
||||
return @directory_document ||= (begin
|
||||
request_uri = self.directory_uri
|
||||
request = ['GET', request_uri, [], []]
|
||||
response = self.transmit_request(request)
|
||||
status, headers, body = response
|
||||
if status == 200 # TODO(bobaman) Better status code handling?
|
||||
|
@ -160,124 +297,130 @@ module Google
|
|||
JSON.parse(merged_body.string)
|
||||
else
|
||||
raise TransmissionError,
|
||||
"Could not retrieve discovery document at: #{self.discovery_uri}"
|
||||
"Could not retrieve discovery document at: #{request_uri}"
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
##
|
||||
# Returns a list of services this client instance has performed discovery
|
||||
# for. This may return multiple versions of the same service.
|
||||
# Returns the parsed discovery document.
|
||||
#
|
||||
# @return [Array]
|
||||
# A list of discovered <code>Google::APIClient::Service</code> objects.
|
||||
def discovered_services
|
||||
return @discovered_services ||= (begin
|
||||
service_names = self.discovery_document['data'].keys()
|
||||
services = []
|
||||
for service_name in service_names
|
||||
versions = self.discovery_document['data'][service_name]
|
||||
for service_version in versions.keys()
|
||||
service_description =
|
||||
self.discovery_document['data'][service_name][service_version]
|
||||
services << ::Google::APIClient::Service.new(
|
||||
service_name,
|
||||
service_version,
|
||||
service_description
|
||||
# @param [String, Symbol] api The service name.
|
||||
# @param [String] version The desired version of the service.
|
||||
# @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
|
||||
request_uri = self.discovery_uri(api, version)
|
||||
request = ['GET', request_uri, [], []]
|
||||
response = self.transmit_request(request)
|
||||
status, headers, body = response
|
||||
if status == 200 # TODO(bobaman) Better status code handling?
|
||||
merged_body = StringIO.new
|
||||
body.each do |chunk|
|
||||
merged_body.write(chunk)
|
||||
end
|
||||
merged_body.rewind
|
||||
JSON.parse(merged_body.string)
|
||||
else
|
||||
raise TransmissionError,
|
||||
"Could not retrieve discovery document at: #{request_uri}"
|
||||
end
|
||||
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
|
||||
services
|
||||
end)
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the service object for a given service name and service version.
|
||||
#
|
||||
# @param [String, Symbol] service_name The service name.
|
||||
# @param [String] service_version The desired version of the service.
|
||||
# @param [String, Symbol] api The service name.
|
||||
# @param [String] version The desired version of the service.
|
||||
#
|
||||
# @return [Google::APIClient::Service] The service object.
|
||||
def discovered_service(service_name, service_version='v1')
|
||||
if !service_name.kind_of?(String) && !service_name.kind_of?(Symbol)
|
||||
# @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 #{service_name.class}."
|
||||
"Expected String or Symbol, got #{api.class}."
|
||||
end
|
||||
service_name = service_name.to_s
|
||||
for service in self.discovered_services
|
||||
if service.name == service_name &&
|
||||
service.version.to_s == service_version.to_s
|
||||
return service
|
||||
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
|
||||
return nil
|
||||
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] service_version The desired version of the service.
|
||||
# @param [String] version The desired version of the service.
|
||||
#
|
||||
# @return [Google::APIClient::Method] The method object.
|
||||
def discovered_method(rpc_name, service_version='v1')
|
||||
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
|
||||
for service in self.discovered_services
|
||||
# This looks kinda weird, but is not a real problem because there's
|
||||
# almost always only one service, and this is memoized anyhow.
|
||||
if service.version.to_s == service_version.to_s
|
||||
return service.to_h[rpc_name] if service.to_h[rpc_name]
|
||||
end
|
||||
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
|
||||
return nil
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the service object with the highest version number.
|
||||
#
|
||||
# <em>Warning</em>: This method should be used with great care. As APIs
|
||||
# are updated, minor differences between versions may cause
|
||||
# @note <em>Warning</em>: 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] service_name The name of the service.
|
||||
# @param [String, Symbol] api The name of the service.
|
||||
#
|
||||
# @return [Google::APIClient::Service] The service object.
|
||||
def latest_service_version(service_name)
|
||||
if !service_name.kind_of?(String) && !service_name.kind_of?(Symbol)
|
||||
# @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 #{service_name.class}."
|
||||
"Expected String or Symbol, got #{api.class}."
|
||||
end
|
||||
service_name = service_name.to_s
|
||||
return (self.discovered_services.select do |service|
|
||||
service.name == service_name
|
||||
end).sort.last
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the user agent used by the client.
|
||||
#
|
||||
# @return [String]
|
||||
# The user agent string used in the User-Agent header.
|
||||
def user_agent
|
||||
return @options[:user_agent]
|
||||
end
|
||||
|
||||
##
|
||||
# Sets the user agent used by the client.
|
||||
#
|
||||
# @param [String, #to_str] new_user_agent
|
||||
# The new user agent string to use in the User-Agent header.
|
||||
def user_agent=(new_user_agent)
|
||||
unless new_user_agent == nil || new_user_agent.respond_to?(:to_str)
|
||||
raise TypeError, "Expected String, got #{new_user_agent.class}."
|
||||
api = api.to_s
|
||||
# TODO(bobaman): Update to use directory API.
|
||||
return self.discovered_apis.detect do |a|
|
||||
a.name == api && a.preferred == true
|
||||
end
|
||||
new_user_agent = new_user_agent.to_str unless new_user_agent == nil
|
||||
@options[:user_agent] = new_user_agent
|
||||
return self.user_agent
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -291,16 +434,17 @@ module Google
|
|||
# @param [Hash, Array] headers The HTTP headers for the request.
|
||||
# @param [Hash] options
|
||||
# The configuration parameters for the request.
|
||||
# - <code>:service_version</code> —
|
||||
# - <code>:version</code> —
|
||||
# The service version. Only used if <code>api_method</code> is a
|
||||
# <code>String</code>. Defaults to <code>'v1'</code>.
|
||||
# - <code>:parser</code> —
|
||||
# The parser for the response.
|
||||
# - <code>:authorization</code> —
|
||||
# The authorization mechanism for the response. Used only if
|
||||
# <code>:signed</code> is <code>true</code>.
|
||||
# - <code>:signed</code> —
|
||||
# <code>true</code> if the request must be signed, <code>false</code>
|
||||
# <code>:authenticated</code> is <code>true</code>.
|
||||
# - <code>:authenticated</code> —
|
||||
# <code>true</code> if the request must be signed or otherwise
|
||||
# authenticated, <code>false</code>
|
||||
# otherwise. Defaults to <code>true</code> if an authorization
|
||||
# mechanism has been set, <code>false</code> otherwise.
|
||||
#
|
||||
|
@ -316,19 +460,27 @@ module Google
|
|||
api_method, parameters={}, body='', headers=[], options={})
|
||||
options={
|
||||
:parser => self.parser,
|
||||
:service_version => 'v1',
|
||||
:version => 'v1',
|
||||
:authorization => self.authorization
|
||||
}.merge(options)
|
||||
# The default value for the :signed option depends on whether an
|
||||
# The default value for the :authenticated option depends on whether an
|
||||
# authorization mechanism has been set.
|
||||
if options[:authorization]
|
||||
options = {:signed => true}.merge(options)
|
||||
options = {:authenticated => true}.merge(options)
|
||||
else
|
||||
options = {:signed => false}.merge(options)
|
||||
options = {:authenticated => false}.merge(options)
|
||||
end
|
||||
if api_method.kind_of?(String) || api_method.kind_of?(Symbol)
|
||||
api_method = api_method.to_s
|
||||
# This method of guessing the API is unreliable. This will fail for
|
||||
# APIs where the first segment of the RPC name does not match the
|
||||
# service name. However, this is a fallback mechanism anyway.
|
||||
# Developers should be passing in a reference to the method, rather
|
||||
# than passing in a string or symbol. This should raise an error
|
||||
# in the case of a mismatch.
|
||||
api = api_method[/^([^.]+)\./, 1]
|
||||
api_method = self.discovered_method(
|
||||
api_method.to_s, options[:service_version]
|
||||
api_method, api, options[:version]
|
||||
)
|
||||
elsif !api_method.kind_of?(::Google::APIClient::Method)
|
||||
raise TypeError,
|
||||
|
@ -339,8 +491,8 @@ module Google
|
|||
raise ArgumentError, "API method could not be found."
|
||||
end
|
||||
request = api_method.generate_request(parameters, body, headers)
|
||||
if options[:signed]
|
||||
request = self.sign_request(request, options[:authorization])
|
||||
if options[:authenticated]
|
||||
request = self.generate_authenticated_request(:request => request)
|
||||
end
|
||||
return request
|
||||
end
|
||||
|
@ -356,7 +508,7 @@ module Google
|
|||
# @param [Hash, Array] headers The HTTP headers for the request.
|
||||
# @param [Hash] options
|
||||
# The configuration parameters for the request.
|
||||
# - <code>:service_version</code> —
|
||||
# - <code>:version</code> —
|
||||
# The service version. Only used if <code>api_method</code> is a
|
||||
# <code>String</code>. Defaults to <code>'v1'</code>.
|
||||
# - <code>:adapter</code> —
|
||||
|
@ -365,9 +517,10 @@ module Google
|
|||
# The parser for the response.
|
||||
# - <code>:authorization</code> —
|
||||
# The authorization mechanism for the response. Used only if
|
||||
# <code>:signed</code> is <code>true</code>.
|
||||
# - <code>:signed</code> —
|
||||
# <code>true</code> if the request must be signed, <code>false</code>
|
||||
# <code>:authenticated</code> is <code>true</code>.
|
||||
# - <code>:authenticated</code> —
|
||||
# <code>true</code> if the request must be signed or otherwise
|
||||
# authenticated, <code>false</code>
|
||||
# otherwise. Defaults to <code>true</code>.
|
||||
#
|
||||
# @return [Array] The response from the API.
|
||||
|
@ -406,25 +559,26 @@ module Google
|
|||
include Enumerable
|
||||
end
|
||||
end
|
||||
unless headers.any? { |k, v| k.downcase == 'user-agent' }
|
||||
headers = headers.to_a.insert(0, ['User-Agent', self.user_agent])
|
||||
if self.user_agent.kind_of?(String)
|
||||
unless headers.any? { |k, v| k.downcase == 'User-Agent'.downcase }
|
||||
headers = headers.to_a.insert(0, ['User-Agent', self.user_agent])
|
||||
end
|
||||
elsif self.user_agent != nil
|
||||
raise TypeError,
|
||||
"Expected User-Agent to be String, got #{self.user_agent.class}"
|
||||
end
|
||||
end
|
||||
::HTTPAdapter.transmit([method, uri, headers, body], adapter)
|
||||
adapter.transmit([method, uri, headers, body])
|
||||
end
|
||||
|
||||
##
|
||||
# Signs a request using the current authorization mechanism.
|
||||
#
|
||||
# @param [Array] request The request to sign.
|
||||
# @param [#generate_authenticated_request] authorization
|
||||
# The authorization mechanism.
|
||||
# @param [Hash] options The options to pass through.
|
||||
#
|
||||
# @return [Array] The signed request.
|
||||
def sign_request(request, authorization=self.authorization)
|
||||
return authorization.generate_authenticated_request(
|
||||
:request => request
|
||||
)
|
||||
# @return [Array] The signed or otherwise authenticated request.
|
||||
def generate_authenticated_request(options={})
|
||||
return authorization.generate_authenticated_request(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,42 +12,37 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
require 'json'
|
||||
require 'addressable/uri'
|
||||
require 'addressable/template'
|
||||
|
||||
require 'google/inflection'
|
||||
require 'google/api_client/errors'
|
||||
|
||||
module Google
|
||||
class APIClient
|
||||
##
|
||||
# An exception that is raised if a method is called with missing or
|
||||
# invalid parameter values.
|
||||
class ValidationError < StandardError
|
||||
end
|
||||
|
||||
##
|
||||
# A service that has been described by a discovery document.
|
||||
class Service
|
||||
class API
|
||||
|
||||
##
|
||||
# Creates a description of a particular version of a service.
|
||||
#
|
||||
# @param [String] service_name
|
||||
# @param [String] api
|
||||
# The identifier for the service. Note that while this frequently
|
||||
# matches the first segment of all of the service's RPC names, this
|
||||
# should not be assumed. There is no requirement that these match.
|
||||
# @param [String] service_version
|
||||
# @param [String] version
|
||||
# The identifier for the service version.
|
||||
# @param [Hash] service_description
|
||||
# @param [Hash] api_description
|
||||
# The section of the discovery document that applies to this service
|
||||
# version.
|
||||
#
|
||||
# @return [Google::APIClient::Service] The constructed service object.
|
||||
def initialize(service_name, service_version, service_description)
|
||||
@name = service_name
|
||||
@version = service_version
|
||||
@description = service_description
|
||||
# @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.resources.each do |resource|
|
||||
method_name = Google::INFLECTOR.underscore(resource.name).to_sym
|
||||
|
@ -63,31 +58,67 @@ module Google
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the id of the service.
|
||||
#
|
||||
# @return [String] The service id.
|
||||
def id
|
||||
return @discovery_document['id']
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the identifier for the service.
|
||||
#
|
||||
# @return [String] The service identifier.
|
||||
attr_reader :name
|
||||
def name
|
||||
return @discovery_document['name']
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the version of the service.
|
||||
#
|
||||
# @return [String] The service version.
|
||||
attr_reader :version
|
||||
def version
|
||||
return @discovery_document['version']
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the parsed section of the discovery document that applies to
|
||||
# this version of the service.
|
||||
#
|
||||
# @return [Hash] The service description.
|
||||
attr_reader :description
|
||||
def description
|
||||
return @discovery_document['description']
|
||||
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 base URI for this version of the service.
|
||||
#
|
||||
# @return [Addressable::URI] The base URI that methods are joined to.
|
||||
def base
|
||||
return @base ||= Addressable::URI.parse(self.description['baseUrl'])
|
||||
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 rest_base
|
||||
if @discovery_document['restBasePath']
|
||||
return @rest_base ||= (
|
||||
self.document_base +
|
||||
Addressable::URI.parse(@discovery_document['restBasePath'])
|
||||
).normalize
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -95,13 +126,13 @@ module Google
|
|||
#
|
||||
# @param [Addressable::URI, #to_str, String] new_base
|
||||
# The new base URI to use for the service.
|
||||
def base=(new_base)
|
||||
@base = Addressable::URI.parse(new_base)
|
||||
def rest_base=(new_rest_base)
|
||||
@rest_base = Addressable::URI.parse(new_rest_base)
|
||||
self.resources.each do |resource|
|
||||
resource.base = @base
|
||||
resource.rest_base = @rest_base
|
||||
end
|
||||
self.methods.each do |method|
|
||||
method.base = @base
|
||||
method.rest_base = @rest_base
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -112,8 +143,8 @@ module Google
|
|||
# @return [Array] A list of {Google::APIClient::Resource} objects.
|
||||
def resources
|
||||
return @resources ||= (
|
||||
(self.description['resources'] || []).inject([]) do |accu, (k, v)|
|
||||
accu << ::Google::APIClient::Resource.new(self.base, k, v)
|
||||
(@discovery_document['resources'] || []).inject([]) do |accu, (k, v)|
|
||||
accu << ::Google::APIClient::Resource.new(self.rest_base, k, v)
|
||||
accu
|
||||
end
|
||||
)
|
||||
|
@ -126,8 +157,8 @@ module Google
|
|||
# @return [Array] A list of {Google::APIClient::Method} objects.
|
||||
def methods
|
||||
return @methods ||= (
|
||||
(self.description['methods'] || []).inject([]) do |accu, (k, v)|
|
||||
accu << ::Google::APIClient::Method.new(self.base, k, v)
|
||||
(@discovery_document['methods'] || []).inject([]) do |accu, (k, v)|
|
||||
accu << ::Google::APIClient::Method.new(self.rest_base, k, v)
|
||||
accu
|
||||
end
|
||||
)
|
||||
|
@ -140,12 +171,12 @@ module Google
|
|||
#
|
||||
# @example
|
||||
# # Discover available methods
|
||||
# method_names = client.discovered_service('buzz').to_h.keys
|
||||
# method_names = client.discovered_api('buzz').to_h.keys
|
||||
def to_h
|
||||
return @hash ||= (begin
|
||||
methods_hash = {}
|
||||
self.methods.each do |method|
|
||||
methods_hash[method.rpc_name] = method
|
||||
methods_hash[method.rpc_method] = method
|
||||
end
|
||||
self.resources.each do |resource|
|
||||
methods_hash.merge!(resource.to_h)
|
||||
|
@ -154,48 +185,6 @@ module Google
|
|||
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]
|
||||
if dotted_version && suffix
|
||||
[dotted_version.split('.').map { |v| v.to_i }, suffix]
|
||||
else
|
||||
[[-1], version]
|
||||
end
|
||||
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.
|
||||
#
|
||||
|
@ -222,10 +211,10 @@ module Google
|
|||
# The section of the discovery document that applies to this resource.
|
||||
#
|
||||
# @return [Google::APIClient::Resource] The constructed resource object.
|
||||
def initialize(base, resource_name, resource_description)
|
||||
@base = base
|
||||
def initialize(rest_base, resource_name, discovery_document)
|
||||
@rest_base = rest_base
|
||||
@name = resource_name
|
||||
@description = resource_description
|
||||
@discovery_document = discovery_document
|
||||
metaclass = (class <<self; self; end)
|
||||
self.resources.each do |resource|
|
||||
method_name = Google::INFLECTOR.underscore(resource.name).to_sym
|
||||
|
@ -258,20 +247,20 @@ module Google
|
|||
# Returns the base URI for this resource.
|
||||
#
|
||||
# @return [Addressable::URI] The base URI that methods are joined to.
|
||||
attr_reader :base
|
||||
attr_reader :rest_base
|
||||
|
||||
##
|
||||
# Updates the hierarchy of resources and methods with the new base.
|
||||
#
|
||||
# @param [Addressable::URI, #to_str, String] new_base
|
||||
# The new base URI to use for the resource.
|
||||
def base=(new_base)
|
||||
@base = Addressable::URI.parse(new_base)
|
||||
def rest_base=(new_rest_base)
|
||||
@rest_base = Addressable::URI.parse(new_rest_base)
|
||||
self.resources.each do |resource|
|
||||
resource.base = @base
|
||||
resource.rest_base = @rest_base
|
||||
end
|
||||
self.methods.each do |method|
|
||||
method.base = @base
|
||||
method.rest_base = @rest_base
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -281,8 +270,8 @@ module Google
|
|||
# @return [Array] A list of {Google::APIClient::Resource} objects.
|
||||
def resources
|
||||
return @resources ||= (
|
||||
(self.description['resources'] || []).inject([]) do |accu, (k, v)|
|
||||
accu << ::Google::APIClient::Resource.new(self.base, k, v)
|
||||
(@discovery_document['resources'] || []).inject([]) do |accu, (k, v)|
|
||||
accu << ::Google::APIClient::Resource.new(self.rest_base, k, v)
|
||||
accu
|
||||
end
|
||||
)
|
||||
|
@ -294,8 +283,8 @@ module Google
|
|||
# @return [Array] A list of {Google::APIClient::Method} objects.
|
||||
def methods
|
||||
return @methods ||= (
|
||||
(self.description['methods'] || []).inject([]) do |accu, (k, v)|
|
||||
accu << ::Google::APIClient::Method.new(self.base, k, v)
|
||||
(@discovery_document['methods'] || []).inject([]) do |accu, (k, v)|
|
||||
accu << ::Google::APIClient::Method.new(self.rest_base, k, v)
|
||||
accu
|
||||
end
|
||||
)
|
||||
|
@ -310,7 +299,7 @@ module Google
|
|||
return @hash ||= (begin
|
||||
methods_hash = {}
|
||||
self.methods.each do |method|
|
||||
methods_hash[method.rpc_name] = method
|
||||
methods_hash[method.rpc_method] = method
|
||||
end
|
||||
self.resources.each do |resource|
|
||||
methods_hash.merge!(resource.to_h)
|
||||
|
@ -337,7 +326,7 @@ module Google
|
|||
##
|
||||
# Creates a description of a particular method.
|
||||
#
|
||||
# @param [Addressable::URI] base
|
||||
# @param [Addressable::URI] rest_base
|
||||
# The base URI for the service.
|
||||
# @param [String] method_name
|
||||
# The identifier for the method.
|
||||
|
@ -345,10 +334,10 @@ module Google
|
|||
# The section of the discovery document that applies to this method.
|
||||
#
|
||||
# @return [Google::APIClient::Method] The constructed method object.
|
||||
def initialize(base, method_name, method_description)
|
||||
@base = base
|
||||
def initialize(rest_base, method_name, discovery_document)
|
||||
@rest_base = rest_base
|
||||
@name = method_name
|
||||
@description = method_description
|
||||
@discovery_document = discovery_document
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -369,15 +358,15 @@ module Google
|
|||
#
|
||||
# @return [Addressable::URI]
|
||||
# The base URI that this method will be joined to.
|
||||
attr_reader :base
|
||||
attr_reader :rest_base
|
||||
|
||||
##
|
||||
# Updates the method with the new base.
|
||||
#
|
||||
# @param [Addressable::URI, #to_str, String] new_base
|
||||
# The new base URI to use for the method.
|
||||
def base=(new_base)
|
||||
@base = Addressable::URI.parse(new_base)
|
||||
def rest_base=(new_rest_base)
|
||||
@rest_base = Addressable::URI.parse(new_rest_base)
|
||||
@uri_template = nil
|
||||
end
|
||||
|
||||
|
@ -385,8 +374,8 @@ module Google
|
|||
# Returns the RPC name for the method.
|
||||
#
|
||||
# @return [String] The RPC name.
|
||||
def rpc_name
|
||||
return self.description['rpcName']
|
||||
def rpc_method
|
||||
return @discovery_document['rpcMethod']
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -399,8 +388,9 @@ module Google
|
|||
# a join operation on a URI, but we have to treat these as Strings
|
||||
# because of the way the discovery document provides the URIs.
|
||||
# This should be fixed soon.
|
||||
return @uri_template ||=
|
||||
Addressable::Template.new(base.to_s + self.description['pathUrl'])
|
||||
return @uri_template ||= Addressable::Template.new(
|
||||
self.rest_base + @discovery_document['restPath']
|
||||
)
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -475,7 +465,7 @@ module Google
|
|||
if !headers.kind_of?(Array) && !headers.kind_of?(Hash)
|
||||
raise TypeError, "Expected Hash or Array, got #{headers.class}."
|
||||
end
|
||||
method = self.description['httpMethod'] || 'GET'
|
||||
method = @discovery_document['httpMethod'] || 'GET'
|
||||
uri = self.generate_uri(parameters)
|
||||
headers = headers.to_a if headers.kind_of?(Hash)
|
||||
return [method, uri.to_str, headers, [body]]
|
||||
|
@ -488,7 +478,7 @@ module Google
|
|||
# @return [Hash] The parameter descriptions.
|
||||
def parameter_descriptions
|
||||
@parameter_descriptions ||= (
|
||||
self.description['parameters'] || {}
|
||||
@discovery_document['parameters'] || {}
|
||||
).inject({}) { |h,(k,v)| h[k]=v; h }
|
||||
end
|
||||
|
||||
|
@ -498,7 +488,7 @@ module Google
|
|||
# @return [Array] The parameters.
|
||||
def parameters
|
||||
@parameters ||= ((
|
||||
self.description['parameters'] || {}
|
||||
@discovery_document['parameters'] || {}
|
||||
).inject({}) { |h,(k,v)| h[k]=v; h }).keys
|
||||
end
|
||||
|
||||
|
@ -552,6 +542,12 @@ module Google
|
|||
end
|
||||
parameters.each do |k, v|
|
||||
if self.parameter_descriptions[k]
|
||||
enum = self.parameter_descriptions[k]['enum']
|
||||
if enum && !enum.include?(v)
|
||||
raise ArgumentError,
|
||||
"Parameter '#{k}' has an invalid value: #{v}. " +
|
||||
"Must be one of #{enum.inspect}."
|
||||
end
|
||||
pattern = self.parameter_descriptions[k]['pattern']
|
||||
if pattern
|
||||
regexp = Regexp.new("^#{pattern}$")
|
||||
|
@ -572,7 +568,8 @@ module Google
|
|||
# @return [String] The method's state, as a <code>String</code>.
|
||||
def inspect
|
||||
sprintf(
|
||||
"#<%s:%#0x NAME:%s>", self.class.to_s, self.object_id, self.rpc_name
|
||||
"#<%s:%#0x NAME:%s>",
|
||||
self.class.to_s, self.object_id, self.rpc_method
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# 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
|
||||
end
|
||||
|
||||
##
|
||||
# An exception that is raised if a method is called with missing or
|
||||
# invalid parameter values.
|
||||
class ValidationError < StandardError
|
||||
end
|
||||
end
|
||||
end
|
|
@ -12,6 +12,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
require 'json'
|
||||
|
||||
module Google
|
||||
|
|
|
@ -12,12 +12,13 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
module Google
|
||||
class APIClient
|
||||
module VERSION
|
||||
MAJOR = 0
|
||||
MINOR = 1
|
||||
TINY = 3
|
||||
MINOR = 2
|
||||
TINY = 0
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||
end
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
module Google
|
||||
if defined?(ActiveSupport::Inflector)
|
||||
INFLECTOR = ActiveSupport::Inflector
|
||||
|
|
|
@ -21,422 +21,422 @@ require 'google/api_client'
|
|||
require 'google/api_client/version'
|
||||
require 'google/api_client/parsers/json_parser'
|
||||
|
||||
describe Google::APIClient, 'unconfigured' do
|
||||
describe Google::APIClient do
|
||||
before do
|
||||
@client = Google::APIClient.new
|
||||
end
|
||||
|
||||
it 'should not be able to determine the discovery URI' do
|
||||
it 'should raise a type error for bogus authorization' do
|
||||
(lambda do
|
||||
@client.discovery_uri
|
||||
end).should raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
||||
describe Google::APIClient, 'configured for a bogus API' do
|
||||
before do
|
||||
@client = Google::APIClient.new(:service => 'bogus')
|
||||
Google::APIClient.new(:authorization => 42)
|
||||
end).should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it 'should not be able to retrieve the discovery document' do
|
||||
it 'should not be able to retrieve the discovery document for a bogus API' do
|
||||
(lambda do
|
||||
@client.discovery_document
|
||||
@client.discovery_document('bogus')
|
||||
end).should raise_error(Google::APIClient::TransmissionError)
|
||||
(lambda do
|
||||
@client.discovered_api('bogus')
|
||||
end).should raise_error(Google::APIClient::TransmissionError)
|
||||
end
|
||||
end
|
||||
|
||||
describe Google::APIClient, 'configured for bogus authorization' do
|
||||
it 'should raise a type error' do
|
||||
it 'should raise an error for bogus services' do
|
||||
(lambda do
|
||||
Google::APIClient.new(:service => 'prediction', :authorization => 42)
|
||||
@client.discovered_api(42)
|
||||
end).should raise_error(TypeError)
|
||||
end
|
||||
end
|
||||
|
||||
describe Google::APIClient, 'configured for the prediction API' do
|
||||
before do
|
||||
@client = Google::APIClient.new(:service => 'prediction')
|
||||
end
|
||||
|
||||
it 'should correctly determine the discovery URI' do
|
||||
@client.discovery_uri.should ===
|
||||
'http://www.googleapis.com/discovery/0.1/describe?api=prediction'
|
||||
end
|
||||
|
||||
it 'should have multiple versions available' do
|
||||
@client.discovered_services.size.should > 1
|
||||
end
|
||||
|
||||
it 'should find APIs that are in the discovery document' do
|
||||
@client.discovered_service('prediction').name.should == 'prediction'
|
||||
@client.discovered_service('prediction').version.should == 'v1'
|
||||
@client.discovered_service(:prediction).name.should == 'prediction'
|
||||
@client.discovered_service(:prediction).version.should == 'v1'
|
||||
end
|
||||
|
||||
it 'should find API versions that are in the discovery document' do
|
||||
@client.discovered_service('prediction', 'v1.1').version.should == 'v1.1'
|
||||
end
|
||||
|
||||
it 'should not find APIs that are not in the discovery document' do
|
||||
@client.discovered_service('bogus').should == nil
|
||||
end
|
||||
|
||||
it 'should raise an error for bogus services' do
|
||||
(lambda do
|
||||
@client.discovered_service(42)
|
||||
@client.preferred_version(42)
|
||||
end).should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it 'should find methods that are in the discovery document' do
|
||||
@client.discovered_method('prediction.training.insert').name.should ==
|
||||
'insert'
|
||||
@client.discovered_method(:'prediction.training.insert').name.should ==
|
||||
'insert'
|
||||
end
|
||||
|
||||
it 'should find methods for versions that are in the discovery document' do
|
||||
@client.discovered_method(
|
||||
'prediction.training.delete', 'v1.1'
|
||||
).should_not == nil
|
||||
end
|
||||
|
||||
it 'should not find methods that are not in the discovery document' do
|
||||
@client.discovered_method('prediction.training.delete', 'v1').should == nil
|
||||
@client.discovered_method('prediction.bogus').should == nil
|
||||
end
|
||||
|
||||
it 'should raise an error for bogus methods' do
|
||||
(lambda do
|
||||
@client.discovered_method(42)
|
||||
end).should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it 'should correctly determine the latest version' do
|
||||
@client.latest_service_version('prediction').version.should_not == 'v1'
|
||||
@client.latest_service_version(:prediction).version.should_not == 'v1'
|
||||
end
|
||||
|
||||
it 'should raise an error for bogus services' do
|
||||
(lambda do
|
||||
@client.latest_service_version(42)
|
||||
end).should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it 'should correctly determine the latest version' do
|
||||
# Sanity check the algorithm
|
||||
@client.discovered_services.clear
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('magic', 'v1', {})
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('magic', 'v1.1', {})
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('magic', 'v1.10', {})
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('magic', 'v10.0.1', {})
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('magic', 'v10.1', {})
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('magic', 'v2.1', {})
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('magic', 'v10.0', {})
|
||||
@client.latest_service_version('magic').version.should == 'v10.1'
|
||||
end
|
||||
|
||||
it 'should correctly determine the latest version' do
|
||||
# Sanity check the algorithm
|
||||
@client.discovered_services.clear
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('one', 'v3', {})
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('two', 'v1', {})
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('two', 'v1.1-r1c3', {})
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('two', 'v2', {})
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('two', 'v2beta1', {})
|
||||
@client.discovered_services <<
|
||||
Google::APIClient::Service.new('two', 'test2', {})
|
||||
@client.latest_service_version('two').version.should == 'v2'
|
||||
end
|
||||
|
||||
it 'should return nil for bogus service names' do
|
||||
# Sanity check the algorithm
|
||||
@client.latest_service_version('bogus').should == nil
|
||||
end
|
||||
|
||||
it 'should generate valid requests' do
|
||||
request = @client.generate_request(
|
||||
'prediction.training.insert',
|
||||
{'query' => '12345'}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
method.should == 'POST'
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/prediction/v1/training?query=12345'
|
||||
(headers.inject({}) { |h,(k,v)| h[k]=v; h }).should == {}
|
||||
body.should respond_to(:each)
|
||||
end
|
||||
|
||||
it 'should generate requests against the correct URIs' do
|
||||
request = @client.generate_request(
|
||||
:'prediction.training.insert',
|
||||
{'query' => '12345'}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/prediction/v1/training?query=12345'
|
||||
end
|
||||
|
||||
it 'should generate requests against the correct URIs' do
|
||||
prediction = @client.discovered_service('prediction', 'v1')
|
||||
request = @client.generate_request(
|
||||
prediction.training.insert,
|
||||
{'query' => '12345'}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/prediction/v1/training?query=12345'
|
||||
end
|
||||
|
||||
it 'should allow modification to the base URIs for testing purposes' do
|
||||
prediction = @client.discovered_service('prediction', 'v1')
|
||||
prediction.base = 'https://testing-domain.googleapis.com/prediction/v1/'
|
||||
request = @client.generate_request(
|
||||
prediction.training.insert,
|
||||
{'query' => '123'}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://testing-domain.googleapis.com/prediction/v1/training?query=123'
|
||||
end
|
||||
|
||||
it 'should generate signed requests' do
|
||||
@client.authorization = :oauth_1
|
||||
@client.authorization.token_credential_key = '12345'
|
||||
@client.authorization.token_credential_secret = '12345'
|
||||
request = @client.generate_request(
|
||||
'prediction.training.insert',
|
||||
{'query' => '12345'}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
headers = headers.inject({}) { |h,(k,v)| h[k]=v; h }
|
||||
headers.keys.should include('Authorization')
|
||||
headers['Authorization'].should =~ /^OAuth/
|
||||
end
|
||||
|
||||
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_secret = '12345'
|
||||
response = @client.execute(
|
||||
'prediction.training.insert',
|
||||
{'query' => '12345'}
|
||||
)
|
||||
status, headers, body = response
|
||||
status.should == 401
|
||||
end
|
||||
|
||||
it 'should raise an error for bogus methods' do
|
||||
(lambda do
|
||||
@client.generate_request(42)
|
||||
end).should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it 'should raise an error for bogus methods' do
|
||||
(lambda do
|
||||
@client.generate_request(@client.discovered_service('prediction'))
|
||||
end).should raise_error(TypeError)
|
||||
end
|
||||
end
|
||||
|
||||
describe Google::APIClient, 'configured for the buzz API' do
|
||||
before do
|
||||
@client = Google::APIClient.new(:service => 'buzz')
|
||||
it 'should not return a preferred version for bogus service names' do
|
||||
@client.preferred_version('bogus').should == nil
|
||||
end
|
||||
|
||||
it 'should correctly determine the discovery URI' do
|
||||
@client.discovery_uri.should ===
|
||||
'http://www.googleapis.com/discovery/0.1/describe?api=buzz'
|
||||
describe 'with the prediction API' do
|
||||
before do
|
||||
@client.authorization = nil
|
||||
end
|
||||
|
||||
it 'should correctly determine the discovery URI' do
|
||||
@client.discovery_uri('prediction').should ===
|
||||
'https://www.googleapis.com/discovery/v0.3/describe/prediction/v1'
|
||||
end
|
||||
|
||||
it 'should correctly generate API objects' do
|
||||
@client.discovered_api('prediction').name.should == 'prediction'
|
||||
@client.discovered_api('prediction').version.should == 'v1'
|
||||
@client.discovered_api(:prediction).name.should == 'prediction'
|
||||
@client.discovered_api(:prediction).version.should == 'v1'
|
||||
end
|
||||
|
||||
it 'should discover methods' do
|
||||
@client.discovered_method(
|
||||
'prediction.training.insert', 'prediction'
|
||||
).name.should == 'insert'
|
||||
@client.discovered_method(
|
||||
:'prediction.training.insert', :prediction
|
||||
).name.should == 'insert'
|
||||
end
|
||||
|
||||
it 'should discover methods' do
|
||||
@client.discovered_method(
|
||||
'prediction.training.delete', 'prediction', 'v1.1'
|
||||
).name.should == 'delete'
|
||||
end
|
||||
|
||||
it 'should not find methods that are not in the discovery document' do
|
||||
@client.discovered_method(
|
||||
'prediction.training.delete', 'prediction', 'v1'
|
||||
).should == nil
|
||||
@client.discovered_method(
|
||||
'prediction.bogus', 'prediction', 'v1'
|
||||
).should == nil
|
||||
end
|
||||
|
||||
it 'should raise an error for bogus methods' do
|
||||
(lambda do
|
||||
@client.discovered_method(42, 'prediction', 'v1')
|
||||
end).should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it 'should raise an error for bogus methods' do
|
||||
(lambda do
|
||||
@client.generate_request(@client.discovered_api('prediction'))
|
||||
end).should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it 'should correctly determine the preferred version' do
|
||||
@client.preferred_version('prediction').version.should_not == 'v1'
|
||||
@client.preferred_version(:prediction).version.should_not == 'v1'
|
||||
end
|
||||
|
||||
it 'should generate valid requests' do
|
||||
request = @client.generate_request(
|
||||
'prediction.training.insert',
|
||||
{'data' => '12345', }
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
method.should == 'POST'
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/prediction/v1/training?data=12345'
|
||||
(headers.inject({}) { |h,(k,v)| h[k]=v; h }).should == {}
|
||||
body.should respond_to(:each)
|
||||
end
|
||||
|
||||
it 'should generate requests against the correct URIs' do
|
||||
request = @client.generate_request(
|
||||
:'prediction.training.insert',
|
||||
{'data' => '12345'}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/prediction/v1/training?data=12345'
|
||||
end
|
||||
|
||||
it 'should generate requests against the correct URIs' do
|
||||
prediction = @client.discovered_api('prediction', 'v1')
|
||||
request = @client.generate_request(
|
||||
prediction.training.insert,
|
||||
{'data' => '12345'}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/prediction/v1/training?data=12345'
|
||||
end
|
||||
|
||||
it 'should allow modification to the base URIs for testing purposes' do
|
||||
prediction = @client.discovered_api('prediction', 'v1')
|
||||
prediction.rest_base =
|
||||
'https://testing-domain.googleapis.com/prediction/v1/'
|
||||
request = @client.generate_request(
|
||||
prediction.training.insert,
|
||||
{'data' => '123'}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://testing-domain.googleapis.com/prediction/v1/training?data=123'
|
||||
end
|
||||
|
||||
it 'should generate OAuth 1 requests' do
|
||||
@client.authorization = :oauth_1
|
||||
@client.authorization.token_credential_key = '12345'
|
||||
@client.authorization.token_credential_secret = '12345'
|
||||
request = @client.generate_request(
|
||||
'prediction.training.insert',
|
||||
{'data' => '12345'}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
headers = headers.inject({}) { |h,(k,v)| h[k]=v; h }
|
||||
headers.keys.should include('Authorization')
|
||||
headers['Authorization'].should =~ /^OAuth/
|
||||
end
|
||||
|
||||
it 'should generate OAuth 2 requests' do
|
||||
@client.authorization = :oauth_2
|
||||
@client.authorization.access_token = '12345'
|
||||
request = @client.generate_request(
|
||||
'prediction.training.insert',
|
||||
{'data' => '12345'}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
headers = headers.inject({}) { |h,(k,v)| h[k]=v; h }
|
||||
headers.keys.should include('Authorization')
|
||||
headers['Authorization'].should =~ /^OAuth/
|
||||
end
|
||||
|
||||
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_secret = '12345'
|
||||
response = @client.execute(
|
||||
'prediction.training.insert',
|
||||
{'data' => '12345'}
|
||||
)
|
||||
status, headers, body = response
|
||||
status.should == 401
|
||||
end
|
||||
|
||||
it 'should not be able to execute improperly authorized requests' do
|
||||
@client.authorization = :oauth_2
|
||||
@client.authorization.access_token = '12345'
|
||||
response = @client.execute(
|
||||
'prediction.training.insert',
|
||||
{'data' => '12345'}
|
||||
)
|
||||
status, headers, body = response
|
||||
status.should == 401
|
||||
end
|
||||
end
|
||||
|
||||
it 'should find APIs that are in the discovery document' do
|
||||
@client.discovered_service('buzz').name.should == 'buzz'
|
||||
@client.discovered_service('buzz').version.should == 'v1'
|
||||
end
|
||||
describe 'with the buzz API' do
|
||||
before do
|
||||
@client.authorization = nil
|
||||
@buzz = @client.discovered_api('buzz')
|
||||
end
|
||||
|
||||
it 'should not find APIs that are not in the discovery document' do
|
||||
@client.discovered_service('bogus').should == nil
|
||||
end
|
||||
it 'should correctly determine the discovery URI' do
|
||||
@client.discovery_uri('buzz').should ===
|
||||
'https://www.googleapis.com/discovery/v0.3/describe/buzz/v1'
|
||||
end
|
||||
|
||||
it 'should find methods that are in the discovery document' do
|
||||
# TODO(bobaman) Fix this when the RPC names are correct
|
||||
@client.discovered_method('chili.activities.list').name.should == 'list'
|
||||
end
|
||||
it 'should find APIs that are in the discovery document' do
|
||||
@client.discovered_api('buzz').name.should == 'buzz'
|
||||
@client.discovered_api('buzz').version.should == 'v1'
|
||||
@client.discovered_api(:buzz).name.should == 'buzz'
|
||||
@client.discovered_api(:buzz).version.should == 'v1'
|
||||
end
|
||||
|
||||
it 'should not find methods that are not in the discovery document' do
|
||||
@client.discovered_method('buzz.bogus').should == nil
|
||||
end
|
||||
it 'should find methods that are in the discovery document' do
|
||||
# TODO(bobaman) Fix this when the RPC names are correct
|
||||
@client.discovered_method(
|
||||
'chili.activities.list', 'buzz'
|
||||
).name.should == 'list'
|
||||
end
|
||||
|
||||
it 'should generate requests against the correct URIs' do
|
||||
# TODO(bobaman) Fix this when the RPC names are correct
|
||||
request = @client.generate_request(
|
||||
'chili.activities.list',
|
||||
{'userId' => 'hikingfan', 'scope' => '@public'},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/buzz/v1/activities/hikingfan/@public'
|
||||
end
|
||||
it 'should not find methods that are not in the discovery document' do
|
||||
@client.discovered_method('buzz.bogus', 'buzz').should == nil
|
||||
end
|
||||
|
||||
it 'should correctly validate parameters' do
|
||||
# TODO(bobaman) Fix this when the RPC names are correct
|
||||
(lambda do
|
||||
@client.generate_request(
|
||||
'chili.activities.list',
|
||||
{'alt' => 'json'},
|
||||
it 'should fail for string RPC names that do not match API name' do
|
||||
(lambda do
|
||||
@client.generate_request(
|
||||
'chili.activities.list',
|
||||
{'alt' => 'json'},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
end).should raise_error(Google::APIClient::TransmissionError)
|
||||
end
|
||||
|
||||
it 'should generate requests against the correct URIs' do
|
||||
request = @client.generate_request(
|
||||
@buzz.activities.list,
|
||||
{'userId' => 'hikingfan', 'scope' => '@public'},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
end).should raise_error(ArgumentError)
|
||||
end
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/buzz/v1/activities/hikingfan/@public'
|
||||
end
|
||||
|
||||
it 'should correctly validate parameters' do
|
||||
# TODO(bobaman) Fix this when the RPC names are correct
|
||||
(lambda do
|
||||
@client.generate_request(
|
||||
'chili.activities.list',
|
||||
{'userId' => 'hikingfan', 'scope' => '@bogus'},
|
||||
it 'should correctly validate parameters' do
|
||||
(lambda do
|
||||
@client.generate_request(
|
||||
@buzz.activities.list,
|
||||
{'alt' => 'json'},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
end).should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it 'should correctly validate parameters' do
|
||||
(lambda do
|
||||
@client.generate_request(
|
||||
@buzz.activities.list,
|
||||
{'userId' => 'hikingfan', 'scope' => '@bogus'},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
end).should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it 'should be able to execute requests without authorization' do
|
||||
response = @client.execute(
|
||||
@buzz.activities.list,
|
||||
{'alt' => 'json', 'userId' => 'hikingfan', 'scope' => '@public'},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
end).should raise_error(ArgumentError)
|
||||
status, headers, body = response
|
||||
status.should == 200
|
||||
end
|
||||
end
|
||||
|
||||
it 'should be able to execute requests without authorization' do
|
||||
# TODO(bobaman) Fix this when the RPC names are correct
|
||||
response = @client.execute(
|
||||
'chili.activities.list',
|
||||
{'alt' => 'json', 'userId' => 'hikingfan', 'scope' => '@public'},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
status, headers, body = response
|
||||
status.should == 200
|
||||
end
|
||||
end
|
||||
|
||||
describe Google::APIClient, 'configured for the latitude API' do
|
||||
before do
|
||||
@client = Google::APIClient.new(:service => 'latitude')
|
||||
end
|
||||
|
||||
it 'should correctly determine the discovery URI' do
|
||||
@client.discovery_uri.should ===
|
||||
'http://www.googleapis.com/discovery/0.1/describe?api=latitude'
|
||||
end
|
||||
|
||||
it 'should find APIs that are in the discovery document' do
|
||||
@client.discovered_service('latitude').name.should == 'latitude'
|
||||
@client.discovered_service('latitude').version.should == 'v1'
|
||||
end
|
||||
|
||||
it 'should not find APIs that are not in the discovery document' do
|
||||
@client.discovered_service('bogus').should == nil
|
||||
end
|
||||
|
||||
it 'should find methods that are in the discovery document' do
|
||||
@client.discovered_method('latitude.currentLocation.get').name.should ==
|
||||
'get'
|
||||
end
|
||||
|
||||
it 'should not find methods that are not in the discovery document' do
|
||||
@client.discovered_method('latitude.bogus').should == nil
|
||||
end
|
||||
|
||||
it 'should generate requests against the correct URIs' do
|
||||
request = @client.generate_request(
|
||||
'latitude.currentLocation.get',
|
||||
{},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/latitude/v1/currentLocation'
|
||||
end
|
||||
|
||||
it 'should not be able to execute requests without authorization' do
|
||||
response = @client.execute(
|
||||
'latitude.currentLocation.get',
|
||||
{},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
status, headers, body = response
|
||||
status.should == 401
|
||||
end
|
||||
end
|
||||
|
||||
describe Google::APIClient, 'configured for the moderator API' do
|
||||
before do
|
||||
@client = Google::APIClient.new(:service => 'moderator')
|
||||
end
|
||||
|
||||
it 'should correctly determine the discovery URI' do
|
||||
@client.discovery_uri.should ===
|
||||
'http://www.googleapis.com/discovery/0.1/describe?api=moderator'
|
||||
end
|
||||
|
||||
it 'should find APIs that are in the discovery document' do
|
||||
@client.discovered_service('moderator').name.should == 'moderator'
|
||||
@client.discovered_service('moderator').version.should == 'v1'
|
||||
end
|
||||
|
||||
it 'should not find APIs that are not in the discovery document' do
|
||||
@client.discovered_service('bogus').should == nil
|
||||
end
|
||||
|
||||
it 'should find methods that are in the discovery document' do
|
||||
@client.discovered_method('moderator.profiles.get').name.should ==
|
||||
'get'
|
||||
end
|
||||
|
||||
it 'should not find methods that are not in the discovery document' do
|
||||
@client.discovered_method('moderator.bogus').should == nil
|
||||
end
|
||||
|
||||
it 'should generate requests against the correct URIs' do
|
||||
request = @client.generate_request(
|
||||
'moderator.profiles.get',
|
||||
{},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/moderator/v1/profiles/@me'
|
||||
end
|
||||
|
||||
it 'should not be able to execute requests without authorization' do
|
||||
response = @client.execute(
|
||||
'moderator.profiles.get',
|
||||
{},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
status, headers, body = response
|
||||
status.should == 401
|
||||
describe 'with the latitude API' do
|
||||
before do
|
||||
@client.authorization = nil
|
||||
@latitude = @client.discovered_api('latitude')
|
||||
end
|
||||
|
||||
it 'should correctly determine the discovery URI' do
|
||||
@client.discovery_uri('latitude').should ===
|
||||
'https://www.googleapis.com/discovery/v0.3/describe/latitude/v1'
|
||||
end
|
||||
|
||||
it 'should find APIs that are in the discovery document' do
|
||||
@client.discovered_api('latitude').name.should == 'latitude'
|
||||
@client.discovered_api('latitude').version.should == 'v1'
|
||||
end
|
||||
|
||||
it 'should find methods that are in the discovery document' do
|
||||
@client.discovered_method(
|
||||
'latitude.currentLocation.get', 'latitude'
|
||||
).name.should == 'get'
|
||||
end
|
||||
|
||||
it 'should not find methods that are not in the discovery document' do
|
||||
@client.discovered_method('latitude.bogus', 'latitude').should == nil
|
||||
end
|
||||
|
||||
it 'should generate requests against the correct URIs' do
|
||||
request = @client.generate_request(
|
||||
'latitude.currentLocation.get',
|
||||
{},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/latitude/v1/currentLocation'
|
||||
end
|
||||
|
||||
it 'should generate requests against the correct URIs' do
|
||||
request = @client.generate_request(
|
||||
@latitude.current_location.get,
|
||||
{},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/latitude/v1/currentLocation'
|
||||
end
|
||||
|
||||
it 'should not be able to execute requests without authorization' do
|
||||
response = @client.execute(
|
||||
'latitude.currentLocation.get',
|
||||
{},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
status, headers, body = response
|
||||
status.should == 401
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with the moderator API' do
|
||||
before do
|
||||
@client.authorization = nil
|
||||
@moderator = @client.discovered_api('moderator')
|
||||
end
|
||||
|
||||
it 'should correctly determine the discovery URI' do
|
||||
@client.discovery_uri('moderator').should ===
|
||||
'https://www.googleapis.com/discovery/v0.3/describe/moderator/v1'
|
||||
end
|
||||
|
||||
it 'should find APIs that are in the discovery document' do
|
||||
@client.discovered_api('moderator').name.should == 'moderator'
|
||||
@client.discovered_api('moderator').version.should == 'v1'
|
||||
end
|
||||
|
||||
it 'should find methods that are in the discovery document' do
|
||||
@client.discovered_method(
|
||||
'moderator.profiles.get', 'moderator'
|
||||
).name.should == 'get'
|
||||
end
|
||||
|
||||
it 'should not find methods that are not in the discovery document' do
|
||||
@client.discovered_method('moderator.bogus', 'moderator').should == nil
|
||||
end
|
||||
|
||||
it 'should generate requests against the correct URIs' do
|
||||
request = @client.generate_request(
|
||||
'moderator.profiles.get',
|
||||
{},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/moderator/v1/profiles/@me'
|
||||
end
|
||||
|
||||
it 'should generate requests against the correct URIs' do
|
||||
request = @client.generate_request(
|
||||
@moderator.profiles.get,
|
||||
{},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
method, uri, headers, body = request
|
||||
uri.should ==
|
||||
'https://www.googleapis.com/moderator/v1/profiles/@me'
|
||||
end
|
||||
|
||||
it 'should not be able to execute requests without authorization' do
|
||||
response = @client.execute(
|
||||
'moderator.profiles.get',
|
||||
{},
|
||||
'',
|
||||
[],
|
||||
{:signed => false}
|
||||
)
|
||||
status, headers, body = response
|
||||
status.should == 401
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,17 +33,20 @@ shared_examples_for 'configurable user agent' do
|
|||
@client.user_agent.should == nil
|
||||
end
|
||||
|
||||
it 'should not allow the user agent to be set to bogus values' do
|
||||
it 'should not allow the user agent to be used with bogus values' do
|
||||
(lambda do
|
||||
@client.user_agent = 42
|
||||
@client.transmit_request(
|
||||
['GET', 'http://www.google.com/', [], []]
|
||||
)
|
||||
end).should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it 'should transmit a User-Agent header when sending requests' do
|
||||
@client.user_agent = 'Custom User Agent/1.2.3'
|
||||
request = ['GET', 'http://www.google.com/', [], []]
|
||||
adapter = HTTPAdapter::MockAdapter.request_adapter do |request, connection|
|
||||
method, uri, headers, body = request
|
||||
adapter = HTTPAdapter::MockAdapter.create do |request_ary, connection|
|
||||
method, uri, headers, body = request_ary
|
||||
headers.should be_any { |k, v| k.downcase == 'user-agent' }
|
||||
headers.each do |k, v|
|
||||
v.should == @client.user_agent if k.downcase == 'user-agent'
|
||||
|
@ -54,7 +57,7 @@ shared_examples_for 'configurable user agent' do
|
|||
end
|
||||
end
|
||||
|
||||
describe Google::APIClient, 'with default configuration' do
|
||||
describe Google::APIClient do
|
||||
before do
|
||||
@client = Google::APIClient.new
|
||||
end
|
||||
|
@ -67,52 +70,60 @@ describe Google::APIClient, 'with default configuration' do
|
|||
@client.parser.should be(Google::APIClient::JSONParser)
|
||||
end
|
||||
|
||||
it 'should not use an authorization mechanism' do
|
||||
@client.authorization.should be_nil
|
||||
it 'should default to OAuth 2' do
|
||||
Signet::OAuth2::Client.should === @client.authorization
|
||||
end
|
||||
|
||||
it_should_behave_like 'configurable user agent'
|
||||
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
|
||||
@client.authorization.temporary_credential_uri.to_s.should ==
|
||||
'https://www.google.com/accounts/OAuthGetRequestToken'
|
||||
@client.authorization.authorization_uri.to_s.should include(
|
||||
'https://www.google.com/accounts/OAuthAuthorizeToken'
|
||||
)
|
||||
@client.authorization.token_credential_uri.to_s.should ==
|
||||
'https://www.google.com/accounts/OAuthGetAccessToken'
|
||||
@client.authorization.client_credential_key.should == 'anonymous'
|
||||
@client.authorization.client_credential_secret.should == 'anonymous'
|
||||
end
|
||||
|
||||
it_should_behave_like 'configurable user agent'
|
||||
end
|
||||
|
||||
describe Google::APIClient, 'with custom pluggable parser' do
|
||||
before do
|
||||
class FakeJsonParser
|
||||
describe 'configured for OAuth 1' do
|
||||
before do
|
||||
@client.authorization = :oauth_1
|
||||
end
|
||||
|
||||
@client = Google::APIClient.new(:parser => FakeJsonParser.new)
|
||||
it 'should use the default OAuth1 client configuration' do
|
||||
@client.authorization.temporary_credential_uri.to_s.should ==
|
||||
'https://www.google.com/accounts/OAuthGetRequestToken'
|
||||
@client.authorization.authorization_uri.to_s.should include(
|
||||
'https://www.google.com/accounts/OAuthAuthorizeToken'
|
||||
)
|
||||
@client.authorization.token_credential_uri.to_s.should ==
|
||||
'https://www.google.com/accounts/OAuthGetAccessToken'
|
||||
@client.authorization.client_credential_key.should == 'anonymous'
|
||||
@client.authorization.client_credential_secret.should == 'anonymous'
|
||||
end
|
||||
|
||||
it_should_behave_like 'configurable user agent'
|
||||
end
|
||||
|
||||
it 'should use the custom parser' do
|
||||
@client.parser.should be_instance_of(FakeJsonParser)
|
||||
describe 'configured for OAuth 2' do
|
||||
before do
|
||||
@client.authorization = :oauth_2
|
||||
end
|
||||
|
||||
# TODO
|
||||
it_should_behave_like 'configurable user agent'
|
||||
end
|
||||
|
||||
it_should_behave_like 'configurable user agent'
|
||||
describe 'with custom pluggable parser' do
|
||||
before do
|
||||
class FakeJsonParser
|
||||
def serialize(value)
|
||||
return "42"
|
||||
end
|
||||
|
||||
def parse(value)
|
||||
return 42
|
||||
end
|
||||
end
|
||||
|
||||
@client.parser = FakeJsonParser.new
|
||||
end
|
||||
|
||||
it 'should use the custom parser' do
|
||||
@client.parser.should be_instance_of(FakeJsonParser)
|
||||
end
|
||||
|
||||
it_should_behave_like 'configurable user agent'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,10 +20,10 @@ namespace :gem do
|
|||
s.rdoc_options.concat ['--main', 'README']
|
||||
|
||||
# Dependencies used in the main library
|
||||
s.add_runtime_dependency('signet', '>= 0.1.4')
|
||||
s.add_runtime_dependency('addressable', '>= 2.2.2')
|
||||
s.add_runtime_dependency('httpadapter', '>= 0.2.0')
|
||||
s.add_runtime_dependency('json', '>= 1.1.9')
|
||||
s.add_runtime_dependency('signet', '~> 0.2.1')
|
||||
s.add_runtime_dependency('addressable', '~> 2.2.2')
|
||||
s.add_runtime_dependency('httpadapter', '~> 1.0.0')
|
||||
s.add_runtime_dependency('json', '>= 1.5.1')
|
||||
s.add_runtime_dependency('extlib', '>= 0.9.15')
|
||||
|
||||
# Dependencies used in the CLI
|
||||
|
|
Loading…
Reference in New Issue