Class: Amazon::AWS::Search::Request
- Inherits:
-
Object
- Object
- Amazon::AWS::Search::Request
- Includes:
- REXML
- Defined in:
- lib/amazon/aws/search.rb
Direct Known Subclasses
Defined Under Namespace
Classes: AccessKeyIdError, LocaleError
Constant Summary collapse
- DIGEST_SUPPORT =
Do we have support for the SHA-256 Secure Hash Algorithm?
Note that Module#constants returns Strings in Ruby 1.8 and Symbols in 1.9.
OpenSSL::Digest.constants.include?( 'SHA256' ) || OpenSSL::Digest.constants.include?( :SHA256 )
- DIGEST =
Requests are authenticated using the SHA-256 Secure Hash Algorithm.
OpenSSL::Digest::Digest.new( 'sha256' )
Instance Attribute Summary collapse
-
#cache ⇒ Object
If @cache has simply been assigned true at some point in time, assign a proper cache object to it when it is referenced.
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#conn ⇒ Object
readonly
Returns the value of attribute conn.
-
#encoding ⇒ Object
Returns the value of attribute encoding.
-
#locale ⇒ Object
Returns the value of attribute locale.
-
#query ⇒ Object
readonly
Returns the value of attribute query.
-
#user_agent ⇒ Object
readonly
Returns the value of attribute user_agent.
Instance Method Summary collapse
-
#initialize(key_id = nil, associate = nil, locale = nil, cache = nil, user_agent = USER_AGENT) ⇒ Request
constructor
This method is used to generate an AWS search request object.
-
#reconnect ⇒ Object
Reconnect to the server if our connection has been lost (due to a time-out, etc.).
-
#search(operation, response_group = nil, nr_pages = 1) ⇒ Object
Perform a search of the AWS database, returning an AWSObject.
-
#sign ⇒ Object
Add a signature to a request object’s query string.
Constructor Details
#initialize(key_id = nil, associate = nil, locale = nil, cache = nil, user_agent = USER_AGENT) ⇒ Request
This method is used to generate an AWS search request object.
key_id is your AWS access key ID. Note that your secret key, used for signing requests, can be specified only in your ~/.amazonrc
configuration file.
associate is your Associates tag (if any), locale is the locale in which you which to work (us for amazon.com, uk for amazon.co.uk, etc.), cache is whether or not you wish to utilise a response cache, and user_agent is the client name to pass when performing calls to AWS. By default, user_agent will be set to a string identifying the Ruby/AWS library and its version number.
locale and cache can also be set later, if you wish to change the current behaviour.
Example:
req = Request.new( '0Y44V8FAFNM119CX4TR2', 'calibanorg-20' )
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/amazon/aws/search.rb', line 71 def initialize(key_id=nil, associate=nil, locale=nil, cache=nil, user_agent=USER_AGENT) @config ||= Amazon::Config.new def_locale = locale locale = 'us' unless locale locale.downcase! key_id ||= @config['key_id'] cache = @config['cache'] if cache.nil? # Take locale from config file if no locale was passed to method. # if @config.key?( 'locale' ) && ! def_locale locale = @config['locale'] end validate_locale( locale ) if key_id.nil? raise AccessKeyIdError, 'key_id may not be nil' end @key_id = key_id @tag = associate || @config['associate'] || DEF_ASSOC[locale] @user_agent = user_agent @cache = unless cache == 'false' || cache == false Amazon::AWS::Cache.new( @config['cache_dir'] ) else nil end # Set the following two variables from the config file. Will be # *nil* if not present in config file. # @api = @config['api'] @encoding = @config['encoding'] self.locale = locale end |
Instance Attribute Details
#cache ⇒ Object
If @cache has simply been assigned true at some point in time, assign a proper cache object to it when it is referenced. Otherwise, just return its value.
147 148 149 150 151 152 153 |
# File 'lib/amazon/aws/search.rb', line 147 def cache # :nodoc: if @cache == true @cache = Amazon::AWS::Cache.new( @config['cache_dir'] ) else @cache end end |
#config ⇒ Object (readonly)
Returns the value of attribute config.
43 44 45 |
# File 'lib/amazon/aws/search.rb', line 43 def config @config end |
#conn ⇒ Object (readonly)
Returns the value of attribute conn.
43 44 45 |
# File 'lib/amazon/aws/search.rb', line 43 def conn @conn end |
#encoding ⇒ Object
Returns the value of attribute encoding.
45 46 47 |
# File 'lib/amazon/aws/search.rb', line 45 def encoding @encoding end |
#locale ⇒ Object
Returns the value of attribute locale.
43 44 45 |
# File 'lib/amazon/aws/search.rb', line 43 def locale @locale end |
#query ⇒ Object (readonly)
Returns the value of attribute query.
43 44 45 |
# File 'lib/amazon/aws/search.rb', line 43 def query @query end |
#user_agent ⇒ Object (readonly)
Returns the value of attribute user_agent.
43 44 45 |
# File 'lib/amazon/aws/search.rb', line 43 def user_agent @user_agent end |
Instance Method Details
#reconnect ⇒ Object
Reconnect to the server if our connection has been lost (due to a time-out, etc.).
187 188 189 190 |
# File 'lib/amazon/aws/search.rb', line 187 def reconnect # :nodoc: connect( self.locale ) self end |
#search(operation, response_group = nil, nr_pages = 1) ⇒ Object
Perform a search of the AWS database, returning an AWSObject.
operation is an object of a subclass of Operation, such as ItemSearch, ItemLookup, etc. It may also be a MultipleOperation object.
response_group, if supplied, is a set of one or more response groups to use in combination with operation for the purpose of determining which data sets AWS should return.
If response_group is nil, Ruby/AWS will instead use the response groups specified by the _@response_group_ attribute of operation. That is now the preferred way of specifying response groups to use with a given operation. The response_group parameter may later be removed from this method altogether.
If response_group is given, it will apply to all sub-operations of operation, if operation is of class MultipleOperation. To use a different set of response groups for each sub-operation, you should assign to the _@response_group_ attribute of each of them before instantiating a MultipleOperation to combine them.
nr_pages is the number of results pages to return. It defaults to 1. If a higher number is given, pages 1 to nr_pages will be returned. If the special value :ALL_PAGES is given, all results pages will be returned.
The maximum page number that can be returned for each type of operation is documented in the AWS Developer’s Guide:
docs.amazonwebservices.com/AWSECommerceService/2009-03-31/DG/index.html?MaximumNumberofPages.html
Note that ItemLookup operations can use three separate pagination parameters. Ruby/AWS, however, uses OfferPage for the purposes of returning multiple pages.
If operation is of class MultipleOperation, the operations specified within will return only the first page, regardless of whether a higher number of pages is requested.
If a block is passed to this method, each successive page of results will be yielded to the block.
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
# File 'lib/amazon/aws/search.rb', line 289 def search(operation, response_group=nil, nr_pages=1) response_group ||= operation.response_group || ResponseGroup.new( :Large ) parameters = Amazon::AWS::SERVICE. merge( { 'AWSAccessKeyId' => @key_id, 'AssociateTag' => @tag } ). merge( operation.params ). merge( response_group.params ) # Check to see whether a particular version of the API has been # requested. If so, overwrite Version with the new value. # parameters.merge!( { 'Version' => @api } ) if @api @query = Amazon::AWS.assemble_query( parameters, @encoding ) page = Amazon::AWS.get_page( self ) # Ruby 1.9 needs to know that the page is UTF-8, not ASCII-8BIT. # page.force_encoding( 'utf-8' ) if RUBY_VERSION >= '1.9.0' doc = Document.new( page ) # Some errors occur at the very top level of the XML. For example, # when no Operation parameter is given. This should not be possible # with user code, but occurred during debugging of this library. # error_check( doc ) # Another possible error results in a document containing nothing # but <Result>Internal Error</Result>. This occurs when a specific # version of the AWS API is requested, in combination with an # operation that did not yet exist in that version of the API. # # For example: # # http://ecs.amazonaws.com/onca/xml?AWSAccessKeyId=foo&Operation=VehicleSearch&Year=2008&ResponseGroup=VehicleMakes&Service=AWSECommerceService&Version=2008-03-03 # if xml = doc.elements['Result'] raise Amazon::AWS::Error::AWSError, xml.text end # Fundamental errors happen at the OperationRequest level. For # example, if an invalid AWSAccessKeyId is used. # error_check( doc.elements['*/OperationRequest'] ) # Check for parameter and value errors deeper down, inside Request. # if operation.kind == 'MultipleOperation' # Everything is a level deeper, because of the # <MultiOperationResponse> container. # # Check for errors in the first operation. # error_check( doc.elements['*/*/*/Request'] ) # Check for errors in the second operation. # error_check( doc.elements['*/*[3]/*/Request'] ) # If second operation is batched, check for errors in its 2nd set # of results. # if batched = doc.elements['*/*[3]/*[2]/Request'] error_check( batched ) end else error_check( doc.elements['*/*/Request'] ) # If operation is batched, check for errors in its 2nd set of # results. # if batched = doc.elements['*/*[3]/Request'] error_check( batched ) end end # FIXME: This doesn't work if a MultipleOperation was used, because # <TotalPages> will be nested one level deeper. It's therefore # currently only possible to return the first page of results # for operations combined in a MultipleOperation. # if doc.elements['*/*[2]/TotalPages'] total_pages = doc.elements['*/*[2]/TotalPages'].text.to_i else total_pages = 1 end # Create a root AWS object and walk the XML response tree. # aws = AWS::AWSObject.new( operation ) aws.walk( doc ) result = aws # If only one page has been requested or only one page is available, # we can stop here. First yield to the block, if given. # if nr_pages == 1 || ( tp = total_pages ) == 1 yield result if block_given? return result end # Limit the number of pages to the maximum number available. # nr_pages = tp.to_i if nr_pages == :ALL_PAGES || nr_pages > tp.to_i if PAGINATION.key? operation.kind page_parameter = PAGINATION[operation.kind]['parameter'] max_pages = PAGINATION[operation.kind]['max_page'] else page_parameter = 'ItemPage' max_pages = 400 end # Iterate over pages 2 and higher, but go no higher than MAX_PAGES. # 2.upto( nr_pages < max_pages ? nr_pages : max_pages ) do |page_nr| @query = Amazon::AWS.assemble_query( parameters.merge( { page_parameter => page_nr } ), @encoding) page = Amazon::AWS.get_page( self ) # Ruby 1.9 needs to know that the page is UTF-8, not ASCII-8BIT. # page.force_encoding( 'utf-8' ) if RUBY_VERSION >= '1.9.0' doc = Document.new( page ) # Check for errors. # error_check( doc.elements['*/OperationRequest'] ) error_check( doc.elements['*/*/Request'] ) # Create a new AWS object and walk the XML response tree. # aws = AWS::AWSObject.new( operation ) aws.walk( doc ) # When dealing with multiple pages, we return not just an # AWSObject, but an array of them. # result = [ result ] unless result.is_a? Array # Append the new object to the array. # result << aws end # Yield each object to the block, if given. # result.each { |r| yield r } if block_given? result end |
#sign ⇒ Object
Add a signature to a request object’s query string. This implicitly also adds a timestamp.
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/amazon/aws/search.rb', line 217 def sign return false unless DIGEST_SUPPORT params = @query[1..-1].split( '&' ).sort.join( '&' ) sign_str = "GET\n%s\n%s\n%s" % [ ENDPOINT[@locale].host, ENDPOINT[@locale].path, params ] Amazon.dprintf( 'Calculating SHA256 HMAC of "%s"...', sign_str ) hmac = OpenSSL::HMAC.digest( DIGEST, @config['secret_key_id'], sign_str ) Amazon.dprintf( 'SHA256 HMAC is "%s"', hmac.inspect ) base64_hmac = [ hmac ].pack( 'm' ).chomp Amazon.dprintf( 'Base64-encoded HMAC is "%s".', base64_hmac ) signature = Amazon.url_encode( base64_hmac ) params << '&Signature=%s' % [ signature ] @query = '?' + params true end |