254 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			254 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
# 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
 | 
						|
    ##
 | 
						|
    # This class wraps a result returned by an API call.
 | 
						|
    class Result
 | 
						|
      extend Forwardable
 | 
						|
      
 | 
						|
      ##
 | 
						|
      # Init the result
 | 
						|
      #
 | 
						|
      # @param [Google::APIClient::Request] request
 | 
						|
      #   The original request
 | 
						|
      # @param [Faraday::Response] response
 | 
						|
      #   Raw HTTP Response
 | 
						|
      def initialize(request, response)
 | 
						|
        @request = request
 | 
						|
        @response = response
 | 
						|
        @media_upload = reference if reference.kind_of?(ResumableUpload)
 | 
						|
      end
 | 
						|
 | 
						|
      # @return [Google::APIClient::Request] Original request object
 | 
						|
      attr_reader :request
 | 
						|
      # @return [Faraday::Response] HTTP response
 | 
						|
      attr_reader :response
 | 
						|
      # @!attribute [r] reference
 | 
						|
      #   @return [Google::APIClient::Request] Original request object
 | 
						|
      #   @deprecated See {#request}
 | 
						|
      alias_method :reference, :request # For compatibility with pre-beta clients
 | 
						|
 | 
						|
      # @!attribute [r] status
 | 
						|
      #   @return [Fixnum] HTTP status code
 | 
						|
      # @!attribute [r] headers
 | 
						|
      #   @return [Hash] HTTP response headers
 | 
						|
      # @!attribute [r] body
 | 
						|
      #   @return [String] HTTP response body
 | 
						|
      def_delegators :@response, :status, :headers, :body
 | 
						|
 | 
						|
      # @!attribute [r] resumable_upload
 | 
						|
      # @return [Google::APIClient::ResumableUpload] For resuming media uploads
 | 
						|
      def resumable_upload        
 | 
						|
        @media_upload ||= (
 | 
						|
          options = self.reference.to_hash.merge(
 | 
						|
            :uri => self.headers['location'],
 | 
						|
            :media => self.reference.media
 | 
						|
          )
 | 
						|
          Google::APIClient::ResumableUpload.new(options)
 | 
						|
        )
 | 
						|
      end
 | 
						|
      
 | 
						|
      ##
 | 
						|
      # Get the content type of the response
 | 
						|
      # @!attribute [r] media_type
 | 
						|
      # @return [String]
 | 
						|
      #  Value of content-type header
 | 
						|
      def media_type
 | 
						|
        _, content_type = self.headers.detect do |h, v|
 | 
						|
          h.downcase == 'Content-Type'.downcase
 | 
						|
        end
 | 
						|
        if content_type
 | 
						|
          return content_type[/^([^;]*);?.*$/, 1].strip.downcase
 | 
						|
        else
 | 
						|
          return nil
 | 
						|
        end
 | 
						|
      end
 | 
						|
      
 | 
						|
      ##
 | 
						|
      # Check if request failed
 | 
						|
      #
 | 
						|
      # @!attribute [r] error?
 | 
						|
      # @return [TrueClass, FalseClass]
 | 
						|
      #   true if result of operation is an error
 | 
						|
      def error?
 | 
						|
        return self.response.status >= 400
 | 
						|
      end
 | 
						|
 | 
						|
      ##
 | 
						|
      # Check if request was successful
 | 
						|
      #
 | 
						|
      # @!attribute [r] success?
 | 
						|
      # @return [TrueClass, FalseClass]
 | 
						|
      #   true if result of operation was successful
 | 
						|
      def success?
 | 
						|
        return !self.error?
 | 
						|
      end
 | 
						|
      
 | 
						|
      ##
 | 
						|
      # Extracts error messages from the response body
 | 
						|
      #
 | 
						|
      # @!attribute [r] error_message
 | 
						|
      # @return [String]
 | 
						|
      #   error message, if available
 | 
						|
      def error_message
 | 
						|
        if self.data?
 | 
						|
          if self.data.respond_to?(:error) &&
 | 
						|
             self.data.error.respond_to?(:message)
 | 
						|
            # You're going to get a terrible error message if the response isn't
 | 
						|
            # parsed successfully as an error.
 | 
						|
            return self.data.error.message
 | 
						|
          elsif self.data['error'] && self.data['error']['message']
 | 
						|
            return self.data['error']['message']
 | 
						|
          end
 | 
						|
        end
 | 
						|
        return self.body
 | 
						|
      end
 | 
						|
 | 
						|
      ##
 | 
						|
      # Check for parsable data in response
 | 
						|
      #
 | 
						|
      # @!attribute [r] data?
 | 
						|
      # @return [TrueClass, FalseClass]
 | 
						|
      #   true if body can be parsed
 | 
						|
      def data?
 | 
						|
        !(self.body.nil? || self.body.empty? || self.media_type != 'application/json')
 | 
						|
      end
 | 
						|
      
 | 
						|
      ##
 | 
						|
      # Return parsed version of the response body.
 | 
						|
      #
 | 
						|
      # @!attribute [r] data
 | 
						|
      # @return [Object, Hash, String]
 | 
						|
      #   Object if body parsable from API schema, Hash if JSON, raw body if unable to parse
 | 
						|
      def data
 | 
						|
        return @data ||= (begin
 | 
						|
          if self.data?
 | 
						|
            media_type = self.media_type
 | 
						|
            data = self.body
 | 
						|
            case media_type
 | 
						|
            when 'application/json'
 | 
						|
              data = MultiJson.load(data)
 | 
						|
              # Strip data wrapper, if present
 | 
						|
              data = data['data'] if data.has_key?('data')
 | 
						|
            else
 | 
						|
              raise ArgumentError,
 | 
						|
                "Content-Type not supported for parsing: #{media_type}"
 | 
						|
            end
 | 
						|
            if @request.api_method && @request.api_method.response_schema
 | 
						|
              # Automatically parse using the schema designated for the
 | 
						|
              # response of this API method.
 | 
						|
              data = @request.api_method.response_schema.new(data)
 | 
						|
              data
 | 
						|
            else
 | 
						|
              # Otherwise, return the raw unparsed value.
 | 
						|
              # This value must be indexable like a Hash.
 | 
						|
              data
 | 
						|
            end
 | 
						|
          end
 | 
						|
        end)
 | 
						|
      end
 | 
						|
 | 
						|
      ##
 | 
						|
      # Get the token used for requesting the next page of data
 | 
						|
      #
 | 
						|
      # @!attribute [r] next_page_token
 | 
						|
      # @return [String]
 | 
						|
      #   next page token
 | 
						|
      def next_page_token
 | 
						|
        if self.data.respond_to?(:next_page_token)
 | 
						|
          return self.data.next_page_token
 | 
						|
        elsif self.data.respond_to?(:[])
 | 
						|
          return self.data["nextPageToken"]
 | 
						|
        else
 | 
						|
          raise TypeError, "Data object did not respond to #next_page_token."
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      ##
 | 
						|
      # Build a request for fetching the next page of data
 | 
						|
      # 
 | 
						|
      # @return [Google::APIClient::Request]
 | 
						|
      #   API request for retrieving next page
 | 
						|
      def next_page
 | 
						|
        merged_parameters = Hash[self.reference.parameters].merge({
 | 
						|
          self.page_token_param => self.next_page_token
 | 
						|
        })
 | 
						|
        # Because Requests can be coerced to Hashes, we can merge them,
 | 
						|
        # preserving all context except the API method parameters that we're
 | 
						|
        # using for pagination.
 | 
						|
        return Google::APIClient::Request.new(
 | 
						|
          Hash[self.reference].merge(:parameters => merged_parameters)
 | 
						|
        )
 | 
						|
      end
 | 
						|
 | 
						|
      ##
 | 
						|
      # Get the token used for requesting the previous page of data
 | 
						|
      #
 | 
						|
      # @!attribute [r] prev_page_token
 | 
						|
      # @return [String]
 | 
						|
      #   previous page token
 | 
						|
      def prev_page_token
 | 
						|
        if self.data.respond_to?(:prev_page_token)
 | 
						|
          return self.data.prev_page_token
 | 
						|
        elsif self.data.respond_to?(:[])
 | 
						|
          return self.data["prevPageToken"]
 | 
						|
        else
 | 
						|
          raise TypeError, "Data object did not respond to #next_page_token."
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      ##
 | 
						|
      # Build a request for fetching the previous page of data
 | 
						|
      # 
 | 
						|
      # @return [Google::APIClient::Request]
 | 
						|
      #   API request for retrieving previous page
 | 
						|
      def prev_page
 | 
						|
        merged_parameters = Hash[self.reference.parameters].merge({
 | 
						|
          self.page_token_param => self.prev_page_token
 | 
						|
        })
 | 
						|
        # Because Requests can be coerced to Hashes, we can merge them,
 | 
						|
        # preserving all context except the API method parameters that we're
 | 
						|
        # using for pagination.
 | 
						|
        return Google::APIClient::Request.new(
 | 
						|
          Hash[self.reference].merge(:parameters => merged_parameters)
 | 
						|
        )
 | 
						|
      end
 | 
						|
      
 | 
						|
      ##
 | 
						|
      # Pagination scheme used by this request/response
 | 
						|
      #
 | 
						|
      # @!attribute [r] pagination_type
 | 
						|
      # @return [Symbol]
 | 
						|
      #  currently always :token
 | 
						|
      def pagination_type
 | 
						|
        return :token
 | 
						|
      end
 | 
						|
 | 
						|
      ##
 | 
						|
      # Name of the field that contains the pagination token
 | 
						|
      #
 | 
						|
      # @!attribute [r] page_token_param
 | 
						|
      # @return [String]
 | 
						|
      #  currently always 'pageToken'
 | 
						|
      def page_token_param
 | 
						|
        return "pageToken"
 | 
						|
      end
 | 
						|
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |