# frozen_string_literal: true require "securerandom" require "json" module MinatoErrorHandler module Errors class MinatoError < StandardError attr_accessor :details, :caused_by attr_reader :http_request def message raise_method_not_implemented_error __method__ end def status_code raise_method_not_implemented_error __method__ end def code self.class.name end def backtrace=(backtrace) set_backtrace(backtrace) end def unique_identfier @unique_identfier ||= SecureRandom.uuid end def to_json(*_args) serialized_hash(serializable_methods_to_log).to_json end def as_json serialized_hash(serializable_methods_to_log).as_json end def json_response serialized_hash(serializable_methods_to_response).as_json end def http_request=(req) return if req.nil? @http_request = { headers: parse_http_request_headers(req.headers), host: req.host, method: req.request_method, path: req.path, query: req.query_parameters, remote: req.remote_ip, scheme: req.scheme } end def stack_trace backtrace end private def serializable_methods_to_log %i[caused_by code details message http_request status_code unique_identfier stack_trace] end def serializable_methods_to_response methods_to_exclude = %i[http_request stack_trace] serializable_methods_to_log.reject { |m| methods_to_exclude.include? m } end def serialized_hash(methods) data = {} methods.each do |method| data[method] = send(method) end data end def parse_http_request_headers(headers) selected_headers = headers.env.filter { |k, _v| k.upcase.start_with? "HTTP" } selected_headers.transform_keys! { |k| k.gsub(/\bHTTP_/, "").downcase } selected_headers end def raise_method_not_implemented_error(method_name) raise "You must define \"#{method_name}\" in your concrete class." end end end end