Merge pull request #583 from sqrrrl/master
Allow using v2 error messages + fix to_json signature
This commit is contained in:
		
						commit
						84f4c7f73e
					
				|  | @ -52,6 +52,9 @@ module Google | |||
|         # | ||||
|         # @return [void] | ||||
|         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) | ||||
|           if request_representation && request_object | ||||
|             header['Content-Type'] ||= JSON_CONTENT_TYPE | ||||
|  | @ -100,15 +103,15 @@ module Google | |||
|         def check_status(status, header = nil, body = nil, message = nil) | ||||
|           case status | ||||
|           when 400, 402...500 | ||||
|             error = parse_error(body) | ||||
|             if error | ||||
|               message = sprintf('%s: %s', error['reason'], error['message']) | ||||
|               raise ERROR_REASON_MAPPING[error['reason']].new( | ||||
|             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?(error['reason']) | ||||
|               ) if ERROR_REASON_MAPPING.key?(reason) | ||||
|             end | ||||
|             super(status, header, body, message) | ||||
|           else | ||||
|  | @ -122,15 +125,45 @@ module Google | |||
| 
 | ||||
|         private | ||||
| 
 | ||||
|         # Attempt to parse a JSON error message, returning the first found error | ||||
|         # Attempt to parse a JSON error message | ||||
|         # @param [String] body | ||||
|         #  HTTP response body | ||||
|         # @return [Hash] | ||||
|         # @return [Array<(String, String)>] | ||||
|         #   Error reason and message | ||||
|         def parse_error(body) | ||||
|           hash = JSON.load(body) | ||||
|           hash['error']['errors'].first | ||||
|           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 | ||||
|           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 | ||||
| 
 | ||||
|         # Convert field names from ruby conventions to original names in JSON | ||||
|  |  | |||
|  | @ -139,7 +139,7 @@ module Google | |||
|           end | ||||
|         end | ||||
| 
 | ||||
|         def to_json | ||||
|         def to_json(*a) | ||||
|           representation = self.class.const_get(:Representation) | ||||
|           representation.new(self).to_json(user_options: { skip_undefined: true }) | ||||
|         end | ||||
|  |  | |||
|  | @ -30,7 +30,8 @@ module Google | |||
|       :header, | ||||
|       :normalize_unicode, | ||||
|       :skip_serialization, | ||||
|       :skip_deserialization) | ||||
|       :skip_deserialization, | ||||
|       :api_format_version) | ||||
| 
 | ||||
|     # General client options | ||||
|     class ClientOptions | ||||
|  | @ -67,6 +68,8 @@ module Google | |||
|       #   @return [Boolean] True if body object should be treated as raw text instead of an object. | ||||
|       # @!attribute [rw] skip_deserialization | ||||
|       #   @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 | ||||
|       # @return [Google::Apis::RequestOptions] | ||||
|  | @ -85,7 +88,7 @@ module Google | |||
|         new_options | ||||
|       end | ||||
|     end | ||||
|      | ||||
| 
 | ||||
|     ClientOptions.default.log_http_requests = false | ||||
|     ClientOptions.default.application_name = 'unknown' | ||||
|     ClientOptions.default.application_version = '0.0.0' | ||||
|  | @ -93,5 +96,6 @@ module Google | |||
|     RequestOptions.default.normalize_unicode = false | ||||
|     RequestOptions.default.skip_serialization = false | ||||
|     RequestOptions.default.skip_deserialization = false | ||||
|     RequestOptions.default.api_format_version = nil | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -280,4 +280,52 @@ EOF | |||
|       expect { command.execute(client) }.to raise_error(/Invalid request/) | ||||
|     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 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue