Module: Dinie::Internal::Errors

Defined in:
lib/dinie/runtime/errors.rb,
sig/dinie/runtime/errors.rbs

Overview

The transport-agnostic error dispatcher (the controlled runtime → generated seam, §4). module_function: methods are declared as instance methods (Steep types self as the module inside them) and are also callable on the module (Errors.from_response).

Constant Summary collapse

REQUEST_ID_HEADER =

Header carrying the per-request correlation id, surfaced as error.request_id.

Returns:

  • (String)
"x-request-id"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.dispatch(type_url, status) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



242
243
244
245
246
247
# File 'lib/dinie/runtime/errors.rb', line 242

def dispatch(type_url, status)
  registry = Dinie::Internal::ERROR_REGISTRY
  (type_url && registry[:by_type][type_url]) ||
    registry[:by_status][status] ||
    fallback_ctor(status)
end

.fallback_ctor(status) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



250
251
252
253
254
# File 'lib/dinie/runtime/errors.rb', line 250

def fallback_ctor(status)
  return Dinie::Internal::ERROR_REGISTRY[:fallback_5xx] if status >= 500

  Dinie::APIStatusError
end

.from_response(status:, headers: {}, body: nil, force: nil) ⇒ Dinie::APIStatusError

Module-function alias (callable as Errors.from_response).

Parameters:

  • status: (Integer)
  • headers: (Hash[untyped, untyped]) (defaults to: {})
  • body: (String, nil) (defaults to: nil)
  • force: (Object) (defaults to: nil)

Returns:



232
233
234
235
236
237
238
239
# File 'lib/dinie/runtime/errors.rb', line 232

def from_response(status:, headers: {}, body: nil, force: nil)
  record = parse_problem(body)
  type_url = string_value(record, :type)
  request_id = header_request_id(headers) || string_value(record, :request_id)
  ctor = force || dispatch(type_url, status)
  ctor.new(status: status, body: record || presentable_body(body), headers: headers || {},
           request_id: request_id)
end

.header_lookup(headers, name) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



278
279
280
281
282
283
284
# File 'lib/dinie/runtime/errors.rb', line 278

def header_lookup(headers, name)
  return nil unless headers.respond_to?(:each)

  target = name.downcase
  headers.each { |key, value| return value if key.to_s.downcase == target }
  nil
end

.header_request_id(headers) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



272
273
274
275
# File 'lib/dinie/runtime/errors.rb', line 272

def header_request_id(headers)
  value = header_lookup(headers, REQUEST_ID_HEADER)
  value.is_a?(Array) ? value.first : value
end

.parse_problem(body) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



257
258
259
260
261
262
263
264
# File 'lib/dinie/runtime/errors.rb', line 257

def parse_problem(body)
  return nil unless body.is_a?(String) && !body.empty?

  parsed = JSON.parse(body, symbolize_names: true)
  parsed.is_a?(Hash) ? parsed : nil
rescue JSON::ParserError
  nil
end

.presentable_body(body) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



267
268
269
# File 'lib/dinie/runtime/errors.rb', line 267

def presentable_body(body)
  body.is_a?(String) && !body.empty? ? body : nil
end

.string_value(record, key) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



287
288
289
290
291
292
# File 'lib/dinie/runtime/errors.rb', line 287

def string_value(record, key)
  return nil unless record

  value = record[key]
  value.is_a?(String) ? value : nil
end

Instance Method Details

#dispatch(type_url, status) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • type_url (String, nil)
  • status (Integer)

Returns:

  • (Object)


242
243
244
245
246
247
# File 'lib/dinie/runtime/errors.rb', line 242

def dispatch(type_url, status)
  registry = Dinie::Internal::ERROR_REGISTRY
  (type_url && registry[:by_type][type_url]) ||
    registry[:by_status][status] ||
    fallback_ctor(status)
end

#fallback_ctor(status) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • status (Integer)

Returns:

  • (Object)


250
251
252
253
254
# File 'lib/dinie/runtime/errors.rb', line 250

def fallback_ctor(status)
  return Dinie::Internal::ERROR_REGISTRY[:fallback_5xx] if status >= 500

  Dinie::APIStatusError
end

#header_lookup(headers, name) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • headers (Object)
  • name (String)

Returns:

  • (Object)


278
279
280
281
282
283
284
# File 'lib/dinie/runtime/errors.rb', line 278

def header_lookup(headers, name)
  return nil unless headers.respond_to?(:each)

  target = name.downcase
  headers.each { |key, value| return value if key.to_s.downcase == target }
  nil
end

#header_request_id(headers) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • headers (Object)

Returns:

  • (Object)


272
273
274
275
# File 'lib/dinie/runtime/errors.rb', line 272

def header_request_id(headers)
  value = header_lookup(headers, REQUEST_ID_HEADER)
  value.is_a?(Array) ? value.first : value
end

#parse_problem(body) ⇒ Hash[Symbol, untyped]?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • body (Object)

Returns:

  • (Hash[Symbol, untyped], nil)


257
258
259
260
261
262
263
264
# File 'lib/dinie/runtime/errors.rb', line 257

def parse_problem(body)
  return nil unless body.is_a?(String) && !body.empty?

  parsed = JSON.parse(body, symbolize_names: true)
  parsed.is_a?(Hash) ? parsed : nil
rescue JSON::ParserError
  nil
end

#presentable_body(body) ⇒ String?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • body (Object)

Returns:

  • (String, nil)


267
268
269
# File 'lib/dinie/runtime/errors.rb', line 267

def presentable_body(body)
  body.is_a?(String) && !body.empty? ? body : nil
end

#string_value(record, key) ⇒ String?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • record (Hash[Symbol, untyped], nil)
  • key (Symbol)

Returns:

  • (String, nil)


287
288
289
290
291
292
# File 'lib/dinie/runtime/errors.rb', line 287

def string_value(record, key)
  return nil unless record

  value = record[key]
  value.is_a?(String) ? value : nil
end