Allow using v2 error messages + fix to_json signature to allow arbitrary args
This commit is contained in:
parent
271f0c86e3
commit
6a4e9184e7
|
@ -52,6 +52,9 @@ module Google
|
||||||
#
|
#
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def prepare!
|
def prepare!
|
||||||
|
if options && 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)
|
query[FIELDS_PARAM] = normalize_fields_param(query[FIELDS_PARAM]) if query.key?(FIELDS_PARAM)
|
||||||
if request_representation && request_object
|
if request_representation && request_object
|
||||||
header['Content-Type'] ||= JSON_CONTENT_TYPE
|
header['Content-Type'] ||= JSON_CONTENT_TYPE
|
||||||
|
@ -100,15 +103,15 @@ module Google
|
||||||
def check_status(status, header = nil, body = nil, message = nil)
|
def check_status(status, header = nil, body = nil, message = nil)
|
||||||
case status
|
case status
|
||||||
when 400, 402...500
|
when 400, 402...500
|
||||||
error = parse_error(body)
|
reason, message = parse_error(body)
|
||||||
if error
|
if reason
|
||||||
message = sprintf('%s: %s', error['reason'], error['message'])
|
message = sprintf('%s: %s', reason, message)
|
||||||
raise ERROR_REASON_MAPPING[error['reason']].new(
|
raise ERROR_REASON_MAPPING[reason].new(
|
||||||
message,
|
message,
|
||||||
status_code: status,
|
status_code: status,
|
||||||
header: header,
|
header: header,
|
||||||
body: body
|
body: body
|
||||||
) if ERROR_REASON_MAPPING.key?(error['reason'])
|
) if ERROR_REASON_MAPPING.key?(reason)
|
||||||
end
|
end
|
||||||
super(status, header, body, message)
|
super(status, header, body, message)
|
||||||
else
|
else
|
||||||
|
@ -122,15 +125,45 @@ module Google
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Attempt to parse a JSON error message, returning the first found error
|
# Attempt to parse a JSON error message
|
||||||
# @param [String] body
|
# @param [String] body
|
||||||
# HTTP response body
|
# HTTP response body
|
||||||
# @return [Hash]
|
# @return [Array<(String, String)>]
|
||||||
|
# Error reason and message
|
||||||
def parse_error(body)
|
def parse_error(body)
|
||||||
hash = JSON.load(body)
|
obj = JSON.load(body)
|
||||||
hash['error']['errors'].first
|
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
|
rescue
|
||||||
nil
|
return [nil, nil]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Extracts details from a v1 error message
|
||||||
|
# @param [Hash] error
|
||||||
|
# Parsed JSON
|
||||||
|
# @return [Array<(String, String)>]
|
||||||
|
# Error reason and message
|
||||||
|
def extract_v1_error_details(error)
|
||||||
|
reason = error['errors'].first['reason']
|
||||||
|
message = error['message']
|
||||||
|
return [reason, message]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Extracts details from a v2error message
|
||||||
|
# @param [Hash] error
|
||||||
|
# Parsed JSON
|
||||||
|
# @return [Array<(String, String)>]
|
||||||
|
# Error reason and message
|
||||||
|
def extract_v2_error_details(error)
|
||||||
|
reason = error['status']
|
||||||
|
message = error['message']
|
||||||
|
return [reason, message]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Convert field names from ruby conventions to original names in JSON
|
# Convert field names from ruby conventions to original names in JSON
|
||||||
|
|
|
@ -139,7 +139,7 @@ module Google
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_json
|
def to_json(*a)
|
||||||
representation = self.class.const_get(:Representation)
|
representation = self.class.const_get(:Representation)
|
||||||
representation.new(self).to_json(user_options: { skip_undefined: true })
|
representation.new(self).to_json(user_options: { skip_undefined: true })
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,7 +30,8 @@ module Google
|
||||||
:header,
|
:header,
|
||||||
:normalize_unicode,
|
:normalize_unicode,
|
||||||
:skip_serialization,
|
:skip_serialization,
|
||||||
:skip_deserialization)
|
:skip_deserialization,
|
||||||
|
:api_format_version)
|
||||||
|
|
||||||
# General client options
|
# General client options
|
||||||
class ClientOptions
|
class ClientOptions
|
||||||
|
@ -67,6 +68,8 @@ module Google
|
||||||
# @return [Boolean] True if body object should be treated as raw text instead of an object.
|
# @return [Boolean] True if body object should be treated as raw text instead of an object.
|
||||||
# @!attribute [rw] skip_deserialization
|
# @!attribute [rw] skip_deserialization
|
||||||
# @return [Boolean] True if response should be returned in raw form instead of deserialized.
|
# @return [Boolean] True if response should be returned in raw form instead of deserialized.
|
||||||
|
# @!attribute [rw] api_format_version
|
||||||
|
# @return [Fixnum] Version of the error format to request/expect.
|
||||||
|
|
||||||
# Get the default options
|
# Get the default options
|
||||||
# @return [Google::Apis::RequestOptions]
|
# @return [Google::Apis::RequestOptions]
|
||||||
|
@ -93,5 +96,6 @@ module Google
|
||||||
RequestOptions.default.normalize_unicode = false
|
RequestOptions.default.normalize_unicode = false
|
||||||
RequestOptions.default.skip_serialization = false
|
RequestOptions.default.skip_serialization = false
|
||||||
RequestOptions.default.skip_deserialization = false
|
RequestOptions.default.skip_deserialization = false
|
||||||
|
RequestOptions.default.api_format_version = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -280,4 +280,52 @@ EOF
|
||||||
expect { command.execute(client) }.to raise_error(/Invalid request/)
|
expect { command.execute(client) }.to raise_error(/Invalid request/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context('with v2 error messages') do
|
||||||
|
let(:command) do
|
||||||
|
cmd = Google::Apis::Core::ApiCommand.new(:get, 'https://www.googleapis.com/zoo/animals')
|
||||||
|
cmd.options.api_format_version = 2
|
||||||
|
cmd
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:example) do
|
||||||
|
json = <<EOF
|
||||||
|
{
|
||||||
|
"error": {
|
||||||
|
"code": 400,
|
||||||
|
"message": "Illegal character ':' in log name",
|
||||||
|
"status": "INVALID_ARGUMENT",
|
||||||
|
"details": [
|
||||||
|
{
|
||||||
|
"@type": "type.googleapis.com/google.logging.v2.WriteLogEntriesPartialErrors",
|
||||||
|
"logEntryErrors": {
|
||||||
|
"0": {
|
||||||
|
"code": 3,
|
||||||
|
"message": "Illegal character ':' in log name"
|
||||||
|
},
|
||||||
|
"1": {
|
||||||
|
"code": 7,
|
||||||
|
"message": "User not authorized."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
stub_request(:get, 'https://www.googleapis.com/zoo/animals')
|
||||||
|
.with(headers: {'X-Goog-Api-Format-Version' => '2'})
|
||||||
|
.to_return(status: [400, 'Invalid Argument'], headers: { 'Content-Type' => 'application/json' }, body: json)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should raise client error' do
|
||||||
|
expect { command.execute(client) }.to raise_error(Google::Apis::ClientError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should raise an error with the reason and message' do
|
||||||
|
expect { command.execute(client) }.to raise_error(
|
||||||
|
/INVALID_ARGUMENT: Illegal character ':' in log name/)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue