Class | Rack::ShowExceptions |
In: |
lib/rack/showexceptions.rb
|
Parent: | Object |
Rack::ShowExceptions catches all exceptions raised from the app it wraps. It shows a useful backtrace with the sourcefile and clickable context, the whole Rack environment and the request data.
Be careful when you use this on public-facing sites as it could reveal information helpful to attackers.
CONTEXT | = | 7 |
# File lib/rack/showexceptions.rb, line 17 17: def initialize(app) 18: @app = app 19: @template = ERB.new(TEMPLATE) 20: end
# File lib/rack/showexceptions.rb, line 22 22: def call(env) 23: @app.call(env) 24: rescue StandardError, LoadError, SyntaxError => e 25: [500, {"Content-Type" => "text/html"}, pretty(env, e)] 26: end
# File lib/rack/showexceptions.rb, line 28 28: def pretty(env, exception) 29: req = Rack::Request.new(env) 30: path = (req.script_name + req.path_info).squeeze("/") 31: 32: frames = exception.backtrace.map { |line| 33: frame = OpenStruct.new 34: if line =~ /(.*?):(\d+)(:in `(.*)')?/ 35: frame.filename = $1 36: frame.lineno = $2.to_i 37: frame.function = $4 38: 39: begin 40: lineno = frame.lineno-1 41: lines = ::File.readlines(frame.filename) 42: frame.pre_context_lineno = [lineno-CONTEXT, 0].max 43: frame.pre_context = lines[frame.pre_context_lineno...lineno] 44: frame.context_line = lines[lineno].chomp 45: frame.post_context_lineno = [lineno+CONTEXT, lines.size].min 46: frame.post_context = lines[lineno+1..frame.post_context_lineno] 47: rescue 48: end 49: 50: frame 51: else 52: nil 53: end 54: }.compact 55: 56: env["rack.errors"].puts "#{exception.class}: #{exception.message}" 57: env["rack.errors"].puts exception.backtrace.map { |l| "\t" + l } 58: env["rack.errors"].flush 59: 60: [@template.result(binding)] 61: end