1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
# frozen_string_literal: true
require 'cgi'
module Aws
module Xml
class ErrorHandler < Seahorse::Client::Handler
def call(context)
@handler.call(context).on(300..599) do |response|
response.error = error(context) unless response.error
response.data = nil
end
end
private
def error(context)
body = context.http_response.body_contents
if body.empty?
code = http_status_error_code(context)
message = ''
data = EmptyStructure.new
else
code, message, data = extract_error(body, context)
end
context[:request_id] = request_id(body)
errors_module = context.client.class.errors_module
error_class = errors_module.error_class(code).new(context, message, data)
error_class
end
def extract_error(body, context)
code = error_code(body, context)
[
code,
error_message(body),
error_data(context, code)
]
end
def error_data(context, code)
data = EmptyStructure.new
if error_rules = context.operation.errors
error_rules.each do |rule|
# for modeled shape with error trait
# match `code` in the error trait before
# match modeled shape name
error_shape_code = rule.shape['error']['code'] if rule.shape['error']
match = (code == error_shape_code || code == rule.shape.name)
if match && rule.shape.members.any?
data = Parser.new(rule).parse(context.http_response.body_contents)
end
end
end
data
rescue Xml::Parser::ParsingError
EmptyStructure.new
end
def error_code(body, context)
if matches = body.match(/<Code>(.+?)<\/Code>/)
remove_prefix(unescape(matches[1]), context)
else
http_status_error_code(context)
end
end
def http_status_error_code(context)
status_code = context.http_response.status_code
{
302 => 'MovedTemporarily',
304 => 'NotModified',
400 => 'BadRequest',
403 => 'Forbidden',
404 => 'NotFound',
412 => 'PreconditionFailed',
413 => 'RequestEntityTooLarge',
}[status_code] || "Http#{status_code}Error"
end
def remove_prefix(error_code, context)
if prefix = context.config.api.metadata['errorPrefix']
error_code.sub(/^#{prefix}/, '')
else
error_code
end
end
def error_message(body)
if matches = body.match(/<Message>(.+?)<\/Message>/m)
unescape(matches[1])
else
''
end
end
def request_id(body)
if matches = body.match(/<RequestId>(.+?)<\/RequestId>/m)
matches[1]
end
end
def unescape(str)
CGI.unescapeHTML(str)
end
end
end
end
|