class Google::Apis::Core::ApiCommand

Command for executing most basic API request with JSON requests/responses

Constants

ERROR_REASON_MAPPING
FIELDS_PARAM
JSON_CONTENT_TYPE

Attributes

client_version[RW]

Client library version. @return [String]

request_object[RW]

Request body to serialize @return [Object]

request_representation[RW]

JSON serializer for request objects @return [Google::Apis::Core::JsonRepresentation]

response_class[RW]

Class to instantiate when de-serializing responses @return [Object]

response_representation[RW]

JSON serializer for response objects @return [Google::Apis::Core::JsonRepresentation]

Public Class Methods

new(method, url, body: nil, client_version: nil) click to toggle source

@param [symbol] method

HTTP method

@param [String,Addressable::URI, Addressable::Template] url

HTTP URL or template

@param [String, read] body

Request body
Calls superclass method
# File lib/google/apis/core/api_command.rb, line 61
def initialize(method, url, body: nil, client_version: nil)
  super(method, url, body: body)
  self.client_version = client_version || Core::VERSION
end

Public Instance Methods

allow_form_encoding?() click to toggle source
Calls superclass method
# File lib/google/apis/core/api_command.rb, line 140
def allow_form_encoding?
  request_representation.nil? && super
end
check_status(status, header = nil, body = nil, message = nil) click to toggle source

Check the response and raise error if needed

@param [Fixnum] status

HTTP status code of response

@param [Hash] header

HTTP response headers

@param [String] body

HTTP response body

@param [String] message

Error message text

@return [void] @raise [Google::Apis::ServerError] An error occurred on the server and the request can be retried @raise [Google::Apis::ClientError] The request is invalid and should not be retried without modification @raise [Google::Apis::AuthorizationError] Authorization is required

Calls superclass method
# File lib/google/apis/core/api_command.rb, line 121
def check_status(status, header = nil, body = nil, message = nil)
  case status
  when 400, 402...500
    reason, message = parse_error(body)
    if reason
      message = sprintf('%s: %s', reason, message)
      raise ERROR_REASON_MAPPING[reason].new(
        message,
        status_code: status,
        header: header,
        body: body
      ) if ERROR_REASON_MAPPING.key?(reason)
    end
    super(status, header, body, message)
  else
    super(status, header, body, message)
  end
end
decode_response_body(content_type, body) click to toggle source

Deserialize the response body if present

@param [String] content_type

Content type of body

@param [String, read] body

Response body

@return [Object]

Response object

noinspection RubyUnusedLocalVariable

Calls superclass method
# File lib/google/apis/core/api_command.rb, line 96
def decode_response_body(content_type, body)
  return super unless response_representation
  return super if options && options.skip_deserialization
  return super if content_type.nil?
  return nil unless content_type.start_with?(JSON_CONTENT_TYPE)
  body = "{}" if body.empty?
  instance = response_class.new
  response_representation.new(instance).from_json(body, unwrap: response_class)
  instance
end
prepare!() click to toggle source

Serialize the request body

@return [void]

Calls superclass method
# File lib/google/apis/core/api_command.rb, line 69
def prepare!
  set_api_client_header
  set_user_project_header
  if options&.api_format_version
    header['X-Goog-Api-Format-Version'] = options.api_format_version.to_s
  end
  query[FIELDS_PARAM] = normalize_fields_param(query[FIELDS_PARAM]) if query.key?(FIELDS_PARAM)
  if request_representation && request_object
    header['Content-Type'] ||= JSON_CONTENT_TYPE
    if options && options.skip_serialization
      self.body = request_object
    else
      self.body = request_representation.new(request_object).to_json(user_options: { skip_undefined: true })
    end
  end
  super
end

Private Instance Methods

extract_v1_error_details(error) click to toggle source

Extracts details from a v1 error message @param [Hash] error

Parsed JSON

@return [Array<(String, String)>]

Error reason and message
# File lib/google/apis/core/api_command.rb, line 199
def extract_v1_error_details(error)
  reason = error['errors'].first['reason']
  message = error['message']
  return [reason, message]
end
extract_v2_error_details(error) click to toggle source

Extracts details from a v2error message @param [Hash] error

Parsed JSON

@return [Array<(String, String)>]

Error reason and message
# File lib/google/apis/core/api_command.rb, line 210
def extract_v2_error_details(error)
  reason = error['status']
  message = error['message']
  return [reason, message]
end
normalize_fields_param(fields) click to toggle source

Convert field names from ruby conventions to original names in JSON

@param [String] fields

Value of 'fields' param

@return [String]

Updated header value
# File lib/google/apis/core/api_command.rb, line 222
def normalize_fields_param(fields)
  # TODO: Generate map of parameter names during code gen. Small possibility that camelization fails
  fields.gsub(/:/, '').gsub(/\w+/) do |str|
    str.gsub(/(?:^|_)([a-z])/){ Regexp.last_match.begin(0) == 0 ? $1 : $1.upcase }
  end
end
parse_error(body) click to toggle source

Attempt to parse a JSON error message @param [String] body

HTTP response body

@return [Array<(String, String)>]

Error reason and message
# File lib/google/apis/core/api_command.rb, line 180
def parse_error(body)
  obj = JSON.load(body)
  error = obj['error']
  if error['details']
    return extract_v2_error_details(error)
  elsif error['errors']
    return extract_v1_error_details(error)
  else
    fail 'Can not parse error message. No "details" or "errors" detected'
  end
rescue
  return [nil, nil]
end
set_api_client_header() click to toggle source
# File lib/google/apis/core/api_command.rb, line 146
def set_api_client_header
  old_xgac = header
    .find_all { |k, v| k.downcase == 'x-goog-api-client' }
    .map { |(a, b)| b }
    .join(' ')
    .split
    .find_all { |s| s !~ %r{^gl-ruby/|^gdcl/} }
    .join(' ')
  # Report 0.x.y versions that are in separate packages as 1.x.y.
  # Thus, reported gdcl/0.x.y versions are monopackage clients, while
  # reported gdcl/1.x.y versions are split clients.
  # In the unlikely event that we want to release post-1.0 versions of
  # these clients, we should start the versioning at 2.0 to avoid
  # confusion.
  munged_client_version = client_version.sub(/^0\./, "1.")
  xgac = "gl-ruby/#{RUBY_VERSION} gdcl/#{munged_client_version}"
  xgac = old_xgac.empty? ? xgac : "#{old_xgac} #{xgac}"
  header.delete_if { |k, v| k.downcase == 'x-goog-api-client' }
  header['X-Goog-Api-Client'] = xgac
end
set_user_project_header() click to toggle source
# File lib/google/apis/core/api_command.rb, line 167
def set_user_project_header
  quota_project_id = options.quota_project
  if !quota_project_id && options&.authorization.respond_to?(:quota_project_id)
    quota_project_id = options.authorization.quota_project_id
  end
  header['X-Goog-User-Project'] = quota_project_id if quota_project_id
end