Class: Rubino::API::Middleware::ErrorHandler
- Inherits:
-
Object
- Object
- Rubino::API::Middleware::ErrorHandler
- 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
- #call(env) ⇒ Object
-
#initialize(app, logger:) ⇒ ErrorHandler
constructor
A new instance of ErrorHandler.
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., details(e)) rescue StandardError => e @logger.error(event: "api.error.unhandled", error: e.class.name, message: e., backtrace: e.backtrace&.first(10)) render(500, "internal_error", "internal server error") end |