Fix warning: instance variable not initialized
[arvados.git] / lib / google / api_client / batch.rb
index 03804821f149475a275e8272c5f75ca5a181d181..45a2e31044e8406671453979aee87be0e1abe21b 100644 (file)
@@ -14,7 +14,7 @@
 
 require 'addressable/uri'
 require 'google/api_client/reference'
-require 'uuidtools'
+require 'securerandom'
 
 module Google
   class APIClient
@@ -24,17 +24,21 @@ module Google
     #
     # @api private
     class BatchedCallResponse
+      # @return [String] UUID of the call
       attr_reader :call_id
-      attr_accessor :status 
+      # @return [Fixnum] HTTP status code
+      attr_accessor :status
+      # @return [Hash] HTTP response headers
       attr_accessor :headers
+      # @return [String] HTTP response body
       attr_accessor :body
 
       ##
       # Initialize the call response
-      # 
+      #
       # @param [String] call_id
       #   UUID of the original call
-      # @param [Integer] status
+      # @param [Fixnum] status
       #   HTTP status
       # @param [Hash] headers
       #   HTTP response headers
@@ -44,27 +48,28 @@ module Google
         @call_id, @status, @headers, @body = call_id, status, headers, body
       end
     end
-    
+
     # Wraps multiple API calls into a single over-the-wire HTTP request.
     #
     # @example
     #
     #     client = Google::APIClient.new
-    #     urlshortener = client.discovered_api('urlshortner')
+    #     urlshortener = client.discovered_api('urlshortener')
     #     batch = Google::APIClient::BatchRequest.new do |result|
     #        puts result.data
     #     end
-    # 
-    #     batch.add(:api_method=>urlshortener.url.insert, :body_object => { 'longUrl' => 'http://example.com/foo' })
-    #     batch.add(:api_method=>urlshortener.url.insert, :body_object => { 'longUrl' => 'http://example.com/bar' })
+    #
+    #     batch.add(:api_method => urlshortener.url.insert, :body_object => { 'longUrl' => 'http://example.com/foo' })
+    #     batch.add(:api_method => urlshortener.url.insert, :body_object => { 'longUrl' => 'http://example.com/bar' })
     #
     #     client.execute(batch)
     #
-    
     class BatchRequest < Request
       BATCH_BOUNDARY = "-----------RubyApiBatchRequest".freeze
 
-      attr_reader :calls, :callbacks
+      # @api private
+      # @return [Array<(String,Google::APIClient::Request,Proc)] List of API calls in the batch
+      attr_reader :calls
 
       ##
       # Creates a new batch request.
@@ -75,18 +80,18 @@ module Google
       #   Callback for every call's response. Won't be called if a call defined
       #   a callback of its own.
       #
-      # @return [Google::APIClient::BatchRequest] 
+      # @return [Google::APIClient::BatchRequest]
       #   The constructed object.
       #
       # @yield [Google::APIClient::Result]
       #   block to be called when result ready
       def initialize(options = {}, &block)
         @calls = []
+        @global_callback = nil
         @global_callback = block if block_given?
         @last_auto_id = 0
-        
-        # TODO(sgomes): Use SecureRandom.uuid, drop UUIDTools when we drop 1.8
-        @base_id = UUIDTools::UUID.random_create.to_s
+
+        @base_id = SecureRandom.uuid
 
         options[:uri] ||= 'https://www.googleapis.com/batch'
         options[:http_method] ||= 'POST'
@@ -100,7 +105,7 @@ module Google
       # automatically be generated, avoiding collisions. If duplicate call IDs
       # are provided, an error will be thrown.
       #
-      # @param [Hash, Google::APIClient::Request] call 
+      # @param [Hash, Google::APIClient::Request] call
       #   the call to be added.
       # @param [String] call_id
       #   the ID to be used for this call. Must be unique
@@ -122,7 +127,7 @@ module Google
               'A call with this ID already exists: %s' % call_id
         end
         callback = block_given? ? block : @global_callback
-        @calls << [call_id, call, callback]        
+        @calls << [call_id, call, callback]
         return self
       end
 
@@ -135,15 +140,19 @@ module Google
       #   the HTTP response.
       def process_http_response(response)
         content_type = find_header('Content-Type', response.headers)
-        boundary = /.*boundary=(.+)/.match(content_type)[1]
-        parts = response.body.split(/--#{Regexp.escape(boundary)}/)
-        parts = parts[1...-1]
-        parts.each do |part|
-          call_response = deserialize_call_response(part)
-          _, call, callback = @calls.assoc(call_response.call_id)
-          result = Google::APIClient::Result.new(call, call_response)
-          callback.call(result) if callback
+        m = /.*boundary=(.+)/.match(content_type)
+        if m
+          boundary = m[1]
+          parts = response.body.split(/--#{Regexp.escape(boundary)}/)
+          parts = parts[1...-1]
+          parts.each do |part|
+            call_response = deserialize_call_response(part)
+            _, call, callback = @calls.assoc(call_response.call_id)
+            result = Google::APIClient::Result.new(call, call_response)
+            callback.call(result) if callback
+          end
         end
+        Google::APIClient::Result.new(self, response)
       end
 
       ##
@@ -157,12 +166,12 @@ module Google
         if @calls.nil? || @calls.empty?
           raise BatchError, 'Cannot make an empty batch request'
         end
-        parts = @calls.map {|(call_id, call, callback)| serialize_call(call_id, call)}
+        parts = @calls.map {|(call_id, call, _callback)| serialize_call(call_id, call)}
         build_multipart(parts, 'multipart/mixed', BATCH_BOUNDARY)
         super
       end
-      
-      
+
+
       protected
 
       ##
@@ -175,7 +184,7 @@ module Google
       # @param [Hash] headers
       #   the hash of headers and their values.
       #
-      # @return [String] 
+      # @return [String]
       #   the value of the desired header.
       def find_header(name, headers)
         _, header = headers.detect do |h, v|
@@ -189,7 +198,7 @@ module Google
       #
       # @api private
       #
-      # @return [String] 
+      # @return [String]
       #  the new, unique ID.
       def new_id
         @last_auto_id += 1
@@ -208,7 +217,7 @@ module Google
       # @param [String] header
       #   Content-ID header value.
       #
-      # @return [String] 
+      # @return [String]
       #   The extracted ID value.
       def header_to_id(header)
         if !header.start_with?('<') || !header.end_with?('>') ||
@@ -216,7 +225,7 @@ module Google
           raise BatchError, 'Invalid value for Content-ID: "%s"' % header
         end
 
-        base, call_id = header[1...-1].split('+')
+        _base, call_id = header[1...-1].split('+')
         return Addressable::URI.unencode(call_id)
       end
 
@@ -228,7 +237,7 @@ module Google
       # @param [String] response
       #   the response to parse.
       #
-      # @return [Array<Hash>, String] 
+      # @return [Array<Hash>, String]
       #   the headers and the body, separately.
       def split_headers_and_body(response)
         headers = {}
@@ -255,12 +264,12 @@ module Google
       # @param [String] call_response
       #   the request to deserialize.
       #
-      # @return [Google::APIClient::BatchedCallResponse] 
+      # @return [Google::APIClient::BatchedCallResponse]
       #   the parsed and converted response.
       def deserialize_call_response(call_response)
         outer_headers, outer_body = split_headers_and_body(call_response)
         status_line, payload = outer_body.split("\n", 2)
-        protocol, status, reason = status_line.split(' ', 3)
+        _protocol, status, _reason = status_line.split(' ', 3)
 
         headers, body = split_headers_and_body(payload)
         content_id = find_header('Content-ID', outer_headers)
@@ -276,16 +285,16 @@ module Google
       # @param [Google::APIClient::Request] call
       #   the call to serialize.
       #
-      # @return [Faraday::UploadIO] 
+      # @return [Faraday::UploadIO]
       #   the serialized request
       def serialize_call(call_id, call)
         method, uri, headers, body = call.to_http_request
-        request = "#{method.to_s.upcase} #{Addressable::URI.parse(uri).path} HTTP/1.1"
+        request = "#{method.to_s.upcase} #{Addressable::URI.parse(uri).request_uri} HTTP/1.1"
         headers.each do |header, value|
           request << "\r\n%s: %s" % [header, value]
         end
         if body
-          # TODO - CompositeIO if body is a stream 
+          # TODO - CompositeIO if body is a stream
           request << "\r\n\r\n"
           if body.respond_to?(:read)
             request << body.read
@@ -295,7 +304,7 @@ module Google
         end
         Faraday::UploadIO.new(StringIO.new(request), 'application/http', 'ruby-api-request', 'Content-ID' => id_to_header(call_id))
       end
-      
+
       ##
       # Convert an id to a Content-ID header value.
       #
@@ -311,7 +320,7 @@ module Google
       def id_to_header(call_id)
         return '<%s+%s>' % [@base_id, Addressable::URI.encode(call_id)]
       end
-      
+
     end
   end
 end
\ No newline at end of file