Class: ActionDispatch::DebugExceptions
Relationships & Source Files | |
Inherits: | Object |
Defined in: | actionpack/lib/action_dispatch/middleware/debug_exceptions.rb |
Overview
This middleware is responsible for logging exceptions and showing a debugging page in case the request is local.
Class Attribute Summary
- .interceptors readonly
Class Method Summary
Instance Method Summary
- #call(env)
- #api_request?(content_type) ⇒ Boolean private
- #create_template(request, wrapper) private
- #invoke_interceptors(request, exception, wrapper) private
- #log_array(logger, lines, request) private
- #log_error(request, wrapper) private
- #log_rescued_responses?(request) ⇒ Boolean private
- #logger(request) private
- #render(status, body, format) private
- #render_exception(request, exception, wrapper) private
- #render_for_api_request(content_type, wrapper) private
- #render_for_browser_request(request, wrapper) private
- #routes_inspector(exception) private
- #stderr_logger private
Constructor Details
.new(app, routes_app = nil, response_format = :default, interceptors = self.class.interceptors) ⇒ DebugExceptions
# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 23
def initialize(app, routes_app = nil, response_format = :default, interceptors = self.class.interceptors) @app = app @routes_app = routes_app @response_format = response_format @interceptors = interceptors end
Class Attribute Details
.interceptors (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 16
cattr_reader :interceptors, instance_accessor: false, default: []
Class Method Details
.register_interceptor(object = nil, &block)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 18
def self.register_interceptor(object = nil, &block) interceptor = object || block interceptors << interceptor end
Instance Method Details
#api_request?(content_type) ⇒ Boolean
(private)
# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 198
def api_request?(content_type) @response_format == :api && !content_type.html? end
#call(env)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 30
def call(env) _, headers, body = response = @app.call(env) if headers[Constants::X_CASCADE] == "pass" body.close if body.respond_to?(:close) raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}" end response rescue Exception => exception request = ActionDispatch::Request.new env backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner") wrapper = ExceptionWrapper.new(backtrace_cleaner, exception) invoke_interceptors(request, exception, wrapper) raise exception unless wrapper.show?(request) render_exception(request, exception, wrapper) end
#create_template(request, wrapper) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 116
def create_template(request, wrapper) DebugView.new( request: request, exception_wrapper: wrapper, # Everything should use the wrapper, but we need to pass `exception` for legacy # code. exception: wrapper.exception, traces: wrapper.traces, show_source_idx: wrapper.source_to_show_id, trace_to_show: wrapper.trace_to_show, routes_inspector: routes_inspector(wrapper), source_extracts: wrapper.source_extracts, ) end
#invoke_interceptors(request, exception, wrapper) (private)
[ GitHub ]#log_array(logger, lines, request) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 172
def log_array(logger, lines, request) return if lines.empty? level = request.get_header("action_dispatch.debug_exception_log_level") if logger.formatter && logger.formatter.respond_to?(: ) logger.add(level, lines.join("\n#{logger.formatter.}")) else logger.add(level, lines.join("\n")) end end
#log_error(request, wrapper) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 135
def log_error(request, wrapper) logger = logger(request) return unless logger return if !log_rescued_responses?(request) && wrapper.rescue_response? trace = wrapper.exception_trace = [] << " " if wrapper.has_cause? << "#{wrapper.exception_class_name} (#{wrapper.})" wrapper.wrapped_causes.each do |wrapped_cause| << "Caused by: #{wrapped_cause.exception_class_name} (#{wrapped_cause.})" end << "\nInformation for: #{wrapper.exception_class_name} (#{wrapper.}):" else << "#{wrapper.exception_class_name} (#{wrapper.}):" end .concat(wrapper.annotated_source_code) << " " .concat(trace) if wrapper.has_cause? wrapper.wrapped_causes.each do |wrapped_cause| << "\nInformation for cause: #{wrapped_cause.exception_class_name} (#{wrapped_cause.}):" .concat(wrapped_cause.annotated_source_code) << " " .concat(wrapped_cause.exception_trace) end end log_array(logger, , request) end
#log_rescued_responses?(request) ⇒ Boolean
(private)
# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 202
def log_rescued_responses?(request) request.get_header("action_dispatch.log_rescued_responses") end
#logger(request) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 184
def logger(request) request.logger || ActionView::Base.logger || stderr_logger end
#render(status, body, format) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 131
def render(status, body, format) [status, { Rack::CONTENT_TYPE => "#{format}; charset=#{Response.default_charset}", Rack::CONTENT_LENGTH => body.bytesize.to_s }, [body]] end
#render_exception(request, exception, wrapper) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 58
def render_exception(request, exception, wrapper) log_error(request, wrapper) if request.get_header("action_dispatch.show_detailed_exceptions") begin content_type = request.formats.first rescue ActionDispatch::Http::MimeNegotiation::InvalidType content_type = Mime[:text] end if api_request?(content_type) render_for_api_request(content_type, wrapper) else render_for_browser_request(request, wrapper) end else raise exception end end
#render_for_api_request(content_type, wrapper) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 92
def render_for_api_request(content_type, wrapper) body = { status: wrapper.status_code, error: Rack::Utils::HTTP_STATUS_CODES.fetch( wrapper.status_code, Rack::Utils::HTTP_STATUS_CODES[500] ), exception: wrapper.exception_inspect, traces: wrapper.traces } to_format = "to_#{content_type.to_sym}" if content_type && body.respond_to?(to_format) formatted_body = body.public_send(to_format) format = content_type else formatted_body = body.to_json format = Mime[:json] end render(wrapper.status_code, formatted_body, format) end
#render_for_browser_request(request, wrapper) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 78
def render_for_browser_request(request, wrapper) template = create_template(request, wrapper) file = "rescues/#{wrapper.rescue_template}" if request.xhr? body = template.render(template: file, layout: false, formats: [:text]) format = "text/plain" else body = template.render(template: file, layout: "rescues/layout") format = "text/html" end render(wrapper.status_code, body, format) end
#routes_inspector(exception) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 192
def routes_inspector(exception) if @routes_app.respond_to?(:routes) && (exception.routing_error? || exception.template_error?) ActionDispatch::Routing::RoutesInspector.new(@routes_app.routes.routes) end end
#stderr_logger (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/middleware/debug_exceptions.rb', line 188
def stderr_logger @stderr_logger ||= ActiveSupport::Logger.new($stderr) end