Class: Rubino::API::Middleware::ErrorHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/rubino/api/middleware/error_handler.rb

Overview

Catches typed Rubino errors and renders them as JSON with the right HTTP status (see STATUS_MAP). Anything else becomes a generic 500 while the full class/message/backtrace are sent to the structured logger, so unhandled crashes never leak internals to clients.

Stack position: second from outermost, just inside Observability, so Observability still sees the final status code on the way out.

Constant Summary collapse

STATUS_MAP =
{
  Rubino::NotFoundError => 404,
  Rubino::ValidationError => 422,
  Rubino::UnauthorizedError => 401,
  Rubino::ConflictError => 409,
  Rubino::PayloadTooLargeError => 413,
  Rubino::UpstreamError => 502
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(app, logger:) ⇒ ErrorHandler

Returns a new instance of ErrorHandler.



25
26
27
28
# File 'lib/rubino/api/middleware/error_handler.rb', line 25

def initialize(app, logger:)
  @app = app
  @logger = logger
end

Instance Method Details

#call(env) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rubino/api/middleware/error_handler.rb', line 30

def call(env)
  @app.call(env)
rescue *STATUS_MAP.keys => e
  base = STATUS_MAP.find { |klass, _| e.is_a?(klass) }
  status = base.last
  render(status, code(e, base.first), e.message, details(e))
rescue StandardError => e
  @logger.error(event: "api.error.unhandled", error: e.class.name, message: e.message,
                backtrace: e.backtrace&.first(10))
  render(500, "internal_error", "internal server error")
end