Module: Typesafe::Errors

Defined in:
lib/typesafe/errors.rb

Overview

Builds error instances from raw HTTP responses.

Class Method Summary collapse

Class Method Details

.from_response(status:, headers: {}, body: nil) ⇒ APIError

Maps a non-2xx response to the matching error class.

Parameters:

  • status (Integer)

    the HTTP status code.

  • headers (Hash, #each_header) (defaults to: {})

    the response headers.

  • body (String, Hash, Array, nil) (defaults to: nil)

    the raw or parsed response body.

Returns:

  • (APIError)

    an instance of the class matching status.



119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/typesafe/errors.rb', line 119

def from_response(status:, headers: {}, body: nil)
  parsed_body = parse_body(body)
  klass = STATUS_CLASSES.fetch(status) do
    (500..599).cover?(status) ? ServerError : APIError
  end

  klass.new(
    status: status,
    body: parsed_body.is_a?(String) ? parsed_body.dup.freeze : parsed_body.freeze,
    headers: normalize_headers(headers).freeze,
    message: message_from_body(parsed_body, status)
  )
end

.message_from_body(parsed_body, status) ⇒ Object



141
142
143
144
145
146
147
148
149
# File 'lib/typesafe/errors.rb', line 141

def message_from_body(parsed_body, status)
  detail = parsed_body.is_a?(Hash) ? parsed_body["detail"] : nil
  case detail
  when String then detail
  when Hash then detail["message"] || detail[:message] || "Invalid request."
  when Array then detail.map { |entry| validation_message(entry) }.join("; ")
  else "The TypeSafe API returned status #{status}."
  end
end

.normalize_headers(headers) ⇒ Object



159
160
161
162
163
164
165
# File 'lib/typesafe/errors.rb', line 159

def normalize_headers(headers)
  return headers.each_header.to_h if headers.respond_to?(:each_header)

  headers.dup
rescue TypeError
  {}
end

.parse_body(body) ⇒ Object



133
134
135
136
137
138
139
# File 'lib/typesafe/errors.rb', line 133

def parse_body(body)
  return body unless body.is_a?(String)

  JSON.parse(body)
rescue JSON::ParserError, TypeError
  body
end

.validation_message(entry) ⇒ Object



151
152
153
154
155
156
157
# File 'lib/typesafe/errors.rb', line 151

def validation_message(entry)
  return entry.to_s unless entry.is_a?(Hash)

  loc = Array(entry["loc"]).join(".")
  msg = entry["msg"] || entry[:msg]
  loc.empty? ? msg.to_s : "#{loc}: #{msg}"
end